You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swagger UI OAuth Cookie与Spring Boot Security OAuth冲突问题咨询

Spring Boot Swagger OAuth2与Angular认证冲突问题解决

问题背景

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:实现会话共用,兼容双端认证

  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)
    )
    
  2. 调整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
    
  3. 优化会话Cookie属性
    在application.yml中配置会话Cookie的跨域和安全属性,确保Swagger和Angular都能正确读取:

    server:
      servlet:
        session:
          cookie:
            path: /
            http-only: true
            secure: true # 生产环境启用,开发环境可关闭
            same-site: Lax # 兼容Swagger UI的跨域授权回调
    
  4. 修正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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 05:40:41