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

Spring Boot Security 6集成Swagger 3:首次调用接口CSRF令牌无效

Spring Boot Security 6 + Swagger 3 首次调用接口触发CSRF令牌无效问题

在Java 17项目中集成Spring Boot Security 6与Swagger 3,访问Swagger UI时先弹出登录窗口,登录成功进入接口概览页,这符合预期。但首次调用接口时,会再次弹出登录窗口,Spring Security日志显示“invalid CSRF token”;取消弹窗并刷新页面后,登录窗口再次出现,重新登录后回到接口概览页,此时调用接口即可成功,CSRF令牌有效。

请问为何会出现该流程?

我的安全配置类如下:

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                /*
                 * Support Javascript based applications (use json instead of HTML)
                 * Otherwise application throws 'Invalid CSRF token'
                 * https://docs.spring.io/spring-security/reference/6.1-SNAPSHOT/servlet/exploits/csrf.html
                */
                .csrf((csrf) -> csrf
                        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                        .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
                )
                .authorizeHttpRequests(requests -> requests
                        .anyRequest().authenticated()
                )
                .httpBasic(Customizer.withDefaults());

        return http.build();
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

我通过在application.yml中配置以下属性启用Swagger 3的CSRF令牌:

springdoc:
  swagger-ui:
    csrf:
      enabled: true

期望实现:登录后首次通过Swagger 3调用接口即可成功。


问题原因分析

1. CSRF令牌的时机匹配问题

首次登录Swagger UI时,Spring Security会生成CSRF令牌并通过Cookie返回,但此时Swagger UI的CSRF逻辑还没完成令牌的抓取和存储——Swagger UI是在页面加载完成后才去读取Cookie中的令牌,你登录后直接调用接口时,请求里携带的令牌要么是空的,要么是旧的无效值,触发Spring Security的CSRF校验失败,进而触发重新认证流程,弹出登录窗口。

2. 刷新后的令牌同步

取消弹窗并刷新页面时,Swagger UI重新加载,会正确读取登录后Cookie里的CSRF令牌并保存,但刷新操作会重置之前的会话状态,所以需要重新登录;登录完成后,Swagger已经持有有效的令牌,后续调用接口时会自动携带,因此请求可以成功。


解决方案

方案1:让Swagger UI及时捕获登录后的CSRF令牌

自定义Swagger UI的页面脚本,在登录完成后主动从Cookie中读取XSRF-TOKEN,并设置到Swagger的全局请求头(对应X-XSRF-TOKEN)中,确保首次调用接口时就能携带有效令牌。

方案2:优化Spring Security的CSRF令牌传递逻辑

修改CsrfTokenRequestHandler的实现,确保CSRF令牌在登录响应返回时就被Swagger UI感知;或者调整CookieCsrfTokenRepository的配置,让令牌的生效时机与Swagger的加载流程匹配。

方案3:测试场景下临时放宽Swagger端点的CSRF校验(不推荐生产环境)

如果只是后端接口测试使用,可以对Swagger相关端点跳过CSRF校验:

.csrf((csrf) -> csrf
        .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
        .csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
        .ignoringRequestMatchers("/v3/api-docs/**", "/swagger-ui/**", "/swagger-ui.html")
)

注意:生产环境禁止此操作,会带来CSRF攻击风险。

内容的提问来源于stack exchange,提问作者DDD1

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 16:51:22