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

如何为指定来源禁用CSRF?Swagger集成认证配置遇阻求助

问题描述

我需要在Swagger中添加认证,但不知道如何为每个请求传递CSRF Token。禁用CSRF保护虽能正常运行,但并非合理方案,因此希望为Swagger相关的特定来源禁用CSRF。

我的SecurityFilterChain配置如下:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
            .and()
            .exceptionHandling().authenticationEntryPoint(authEntryPoint)
            .and()
            .authorizeHttpRequests()
            .antMatchers("/swagger-resources/**","/v2/api-docs","/swagger-ui/**","/auth/**","/user","/csrf")
            .permitAll()
            .anyRequest()
            .authenticated()
            .and()
            .sessionManagement()
            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .authenticationProvider(authenticationProvider)
            .addFilterBefore(malformedTokenHandler, LogoutFilter.class)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

另外我的SwaggerConfig类如下:

public class SwaggerConfig {

    @Bean
    public Docket api() {
        return new Docket(DocumentationType.SWAGGER_2)
                .securityContexts(Arrays.asList(securityContext()))
                .securitySchemes(Arrays.asList(apiKey()))
                .select()
                .apis(RequestHandlerSelectors.any())
                .paths(PathSelectors.any())
                .build();
    }
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");

        registry.addResourceHandler("/webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }
    private ApiKey apiKey() {
        return new ApiKey("JWT", "Authorization", "header");
    }
 
    List<SecurityReference> defaultAuth() {
        AuthorizationScope authorizationScope
                = new AuthorizationScope("global", "accessEverything");
        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
        authorizationScopes[0] = authorizationScope;
        return Arrays.asList(new SecurityReference("JWT", authorizationScopes));
    }
 
 private List<Parameter> operationParameters(CsrfTokenRepository csrfTokenRepository) {
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()).getRequest();
        CsrfToken csrfToken = csrfTokenRepository.loadToken(request);
        return Arrays.asList(
                new ParameterBuilder()
                        .name("X-CSRF-TOKEN")
                        .modelRef(new ModelRef("string"))
                        .parameterType("header")
                        .defaultValue(csrfToken.getToken())
                        .required(false)
                        .build());
    }
}

我尝试添加以下配置,但并未生效:

http.csrf().ignoringAntMatchers("/swagger-resources/**","/v2/api-docs","/swagger-ui/**")

解决方案

1. 修正CSRF忽略路径的配置方式

你之前的链式调用写法有误,需要将ignoringAntMatchers和csrfTokenRepository放在同一段CSRF配置中。使用Spring Security 5.2+推荐的Lambda式配置可以避免此类错误,修改后的SecurityFilterChain如下:

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            // 统一配置CSRF规则
            .csrf(csrf -> csrf
                    .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
                    .ignoringAntMatchers(
                        "/swagger-resources/**",
                        "/v2/api-docs",
                        "/swagger-ui/**",
                        "/swagger-ui.html" // 补充该路径,避免遗漏Swagger入口页
                    ))
            .exceptionHandling().authenticationEntryPoint(authEntryPoint)
            .and()
            .authorizeHttpRequests(auth -> auth
                    .antMatchers("/swagger-resources/**","/v2/api-docs","/swagger-ui/**","/auth/**","/user","/csrf")
                    .permitAll()
                    .anyRequest().authenticated())
            .sessionManagement(session -> session
                    .sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authenticationProvider(authenticationProvider)
            .addFilterBefore(malformedTokenHandler, LogoutFilter.class)
            .addFilterBefore(jwtAuthFilter, UsernamePasswordAuthenticationFilter.class);

    return http.build();
}

2. (可选)让Swagger自动携带CSRF Token

如果不想忽略Swagger路径的CSRF校验,可修改SwaggerConfig为所有接口添加全局CSRF请求头参数,方便手动输入或自动读取Cookie值:

@Bean
public Docket api() {
    return new Docket(DocumentationType.SWAGGER_2)
            .securityContexts(Arrays.asList(securityContext()))
            .securitySchemes(Arrays.asList(apiKey()))
            // 添加全局CSRF Token参数
            .globalOperationParameters(Arrays.asList(
                    new ParameterBuilder()
                            .name("X-CSRF-TOKEN")
                            .modelRef(new ModelRef("string"))
                            .parameterType("header")
                            .description("从Cookie的XSRF-TOKEN字段获取")
                            .required(true)
                            .build()
            ))
            .select()
            .apis(RequestHandlerSelectors.any())
            .paths(PathSelectors.any())
            .build();
}

注:CookieCsrfTokenRepository默认会将CSRF Token存入名为XSRF-TOKEN的Cookie中,Swagger UI通常会自动读取该Cookie并填充请求头,若未自动生效可手动复制Cookie值填入参数框。

3. 排查路径匹配问题

若忽略路径仍不生效,检查以下两点:

  • 确认项目是否有上下文路径(Context Path),若有需在匹配路径前添加,例如/your-app/swagger-ui/**
  • 改用mvcMatchers替代antMatchers,它更贴合Spring MVC的路径匹配规则:
.ignoringMvcMatchers("/swagger-resources/**", "/v2/api-docs", "/swagger-ui/**")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 22:25:30