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

Spring Boot 3.x迁移后JWTRequestFilter未生效问题排查

Spring Boot 3(Security 6)多SecurityFilterChain配置问题解决

你遇到的问题核心是Spring Security 6中多个SecurityFilterChain的匹配逻辑和优先级处理,原来基于WebSecurityConfigurerAdapter的多配置方式,迁移到SecurityFilterChain后需要明确每个链的securityMatcher和@Order,否则会出现路径覆盖或过滤器不生效的情况。

直接给你可行的配置方案,完全匹配你的三个需求:

第一步:配置Swagger专属的SecurityFilterChain(高优先级)

这个链只处理Swagger相关路径,配置账号密码认证,并且设置更高优先级确保先匹配:

@Configuration
@Order(1) // 数字越小优先级越高,确保Swagger路径先被这个链处理
public class SwaggerSecurityConfig {

    @Bean
    public SecurityFilterChain swaggerSecurityFilterChain(HttpSecurity http) throws Exception {
        http
            // 明确指定该链只处理Swagger相关路径,这是关键!
            .securityMatcher("/swagger-ui/**", "/v3/api-docs/**")
            .authorizeHttpRequests(auth -> auth
                .anyRequest().authenticated()
            )
            // 用HTTP Basic认证对应原来的账号密码登录
            .httpBasic(Customizer.withDefaults());

        return http.build();
    }

    // 配置Swagger的认证用户(如果是自定义用户体系,替换成你的UserDetailsService即可)
    @Bean
    public UserDetailsService swaggerUserDetailsService() {
        UserDetails swaggerUser = User.withUsername("swagger_admin")
            .password(passwordEncoder().encode("swagger_pass"))
            .roles("SWAGGER")
            .build();
        return new InMemoryUserDetailsManager(swaggerUser);
    }

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

第二步:配置JWT的SecurityFilterChain(低优先级)

这个链处理剩余所有路径,排除登录端点,添加JWT过滤器:

@Configuration
@Order(2) // 优先级低于Swagger链,只处理未被前面链匹配的路径
public class JwtSecurityConfig {

    private final JWTRequestFilter jwtRequestFilter;

    // 注入你的JWT过滤器
    public JwtSecurityConfig(JWTRequestFilter jwtRequestFilter) {
        this.jwtRequestFilter = jwtRequestFilter;
    }

    @Bean
    public SecurityFilterChain jwtSecurityFilterChain(HttpSecurity http) throws Exception {
        http
            // 处理所有路径,但Swagger路径已经被前面的链拦截,不会走到这里
            .securityMatcher("/**")
            .authorizeHttpRequests(auth -> auth
                // 登录端点放行,不需要JWT验证
                .requestMatchers("/v1/auth/login").permitAll()
                // 其他所有端点都需要认证
                .anyRequest().authenticated()
            )
            // 在用户名密码认证过滤器之前添加JWT过滤器
            .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
            // JWT是无状态的,禁用session
            .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            // JWT场景下禁用CSRF
            .csrf(csrf -> csrf.disable());

        return http.build();
    }
}

关键注意点

  1. 必须用securityMatcher划分链的处理范围:
    这是Spring Security 6和旧版本最大的区别之一,原来的antMatcher是在authorizeHttpRequests里配置,现在如果不在链的顶层用securityMatcher,该链会默认处理所有路径,导致后面的链完全不生效(这就是你之前JWT过滤器不触发的原因)。

  2. @Order的优先级要正确:
    处理特定路径的链(比如Swagger)要设置更小的Order值,确保先匹配;通用链(JWT)设置更大的Order值,处理剩余路径。

  3. 避免重复路径配置:
    两个链的处理路径不要重叠,Swagger的链已经覆盖了/swagger相关路径,JWT链不需要再处理这些路径,自然不会把JWT过滤器加到Swagger端点上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 13:03:30