Swagger UI OAuth Cookie与Spring Boot Security OAuth冲突问题咨询
问题背景
Spring Boot项目引入springdoc-openapi-ui 1.6.12并配置带PKCE的OAuth2后,Swagger UI点击「authorize」可正常跳转SSO登录并发送请求,但Angular前端陷入/login路由循环,请求返回401错误。经排查,问题源于Swagger的OAuth流程与Spring Security/Angular共享同一会话Cookie,导致认证状态相互干扰。需实现Swagger UI与Angular共用会话,或定位并解决冲突根源。
现有配置
SpringDoc配置
springdoc: swagger-ui: path: /api-docs tagsSorter: alpha oauth: clientId: "XXX" clientSecret: "XXX" use-pkce-with-authorization-code-grant: true oAuthFlow: authorizationUrl: "XXX/as/authorization.oauth2" tokenUrl: "XXX/as/token.oauth2" scope : XXX profile groups XXX email
Spring Security配置
@Override protected void configure(HttpSecurity http) throws Exception { http .cors().configurationSource(corsConfigurationSource()) .and().csrf().disable() .headers() .frameOptions().disable() .httpStrictTransportSecurity() .includeSubDomains(false) .maxAgeInSeconds(60*60*24*5) .and().and() .authorizeRequests(a -> a // Management endpoints .antMatchers( "/health" + MATCH_ALL, "/info", "/prometheus", "/loggers" + MATCH_ALL, "/metrics" + MATCH_ALL ).permitAll() // Authentication .antMatchers(Routes.CURRENT_USER).permitAll() .antMatchers("/oauth2/authorization/XXX").permitAll() .antMatchers(Routes.LOGIN).authenticated() // Preflight requests .antMatchers(HttpMethod.OPTIONS).permitAll() // Applications .antMatchers(Routes.XXX.BASE + MATCH_ALL).hasAuthority(AuthorityUtil.AUTHORITY_XXX) ) // By setting the login page here, Spring won't ask which provider we want to use .oauth2Login().loginPage("/oauth2/authorization/XXX") .and() .oauth2ResourceServer(OAuth2ResourceServerConfigurer::opaqueToken) ; } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.applyPermitDefaultValues(); config.setAllowedOriginPatterns(List.of("*")); config.setAllowedMethods(List.of("*")); config.setAllowedHeaders(List.of("*")); config.setAllowCredentials(true); config.setMaxAge(1800L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration(MATCH_ALL, config); return source; }
问题根源
Swagger UI的OAuth2授权码流程(带PKCE)与Angular依赖的Spring Securityoauth2Login流程共享会话Cookie时,会出现状态冲突:
- Swagger UI在授权过程中会向会话写入临时授权状态,覆盖或干扰Angular端依赖的认证会话信息;
- Angular端检测到会话未正确认证,触发登录重定向,而Swagger的会话状态又导致重定向循环。
解决方案
方案1:实现会话共用,兼容双端认证
放行Swagger相关路径,避免触发登录重定向
修改Spring Security的authorizeRequests规则,新增Swagger文档路径的放行配置,确保Swagger UI的授权流程不会被oauth2Login的重定向逻辑干扰:.authorizeRequests(a -> a // 新增:放行Swagger所有相关路径 .antMatchers("/api-docs/**", "/v3/api-docs/**", "/swagger-ui/**").permitAll() // 原有规则保留 .antMatchers("/health" + MATCH_ALL, "/info", "/prometheus", "/loggers" + MATCH_ALL, "/metrics" + MATCH_ALL).permitAll() .antMatchers(Routes.CURRENT_USER).permitAll() .antMatchers("/oauth2/authorization/XXX").permitAll() .antMatchers(Routes.LOGIN).authenticated() .antMatchers(HttpMethod.OPTIONS).permitAll() .antMatchers(Routes.XXX.BASE + MATCH_ALL).hasAuthority(AuthorityUtil.AUTHORITY_XXX) )调整Swagger OAuth2配置,适配PKCE模式
PKCE模式下,公开客户端(如Swagger UI)无需配置clientSecret,移除该配置项,确保与后端oauth2Login使用同一客户端ID和授权地址:springdoc: swagger-ui: path: /api-docs tagsSorter: alpha oauth: clientId: "XXX" use-pkce-with-authorization-code-grant: true oAuthFlow: authorizationUrl: "XXX/as/authorization.oauth2" tokenUrl: "XXX/as/token.oauth2" scope : XXX profile groups XXX email优化会话Cookie属性
在application.yml中配置会话Cookie的跨域和安全属性,确保Swagger和Angular都能正确读取:server: servlet: session: cookie: path: / http-only: true secure: true # 生产环境启用,开发环境可关闭 same-site: Lax # 兼容Swagger UI的跨域授权回调修正Angular端请求配置
确保Angular所有请求携带withCredentials: true,保证会话Cookie被正确传递:// Angular HTTP拦截器示例 @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const authReq = req.clone({ withCredentials: true }); return next.handle(authReq); } }
方案2:分离双端会话(备选)
若共用会话仍存在冲突,可为Swagger UI配置独立的客户端ID:
- 在SSO服务端新增一个仅用于Swagger的客户端,开启PKCE支持;
- 修改SpringDoc配置中的
clientId为新的客户端ID; - 保持Spring Security对Swagger路径的放行配置,让Swagger使用独立会话,避免与Angular冲突。
内容的提问来源于stack exchange,提问作者faycal

