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(); } }
关键注意点
必须用
securityMatcher划分链的处理范围:
这是Spring Security 6和旧版本最大的区别之一,原来的antMatcher是在authorizeHttpRequests里配置,现在如果不在链的顶层用securityMatcher,该链会默认处理所有路径,导致后面的链完全不生效(这就是你之前JWT过滤器不触发的原因)。@Order的优先级要正确:
处理特定路径的链(比如Swagger)要设置更小的Order值,确保先匹配;通用链(JWT)设置更大的Order值,处理剩余路径。避免重复路径配置:
两个链的处理路径不要重叠,Swagger的链已经覆盖了/swagger相关路径,JWT链不需要再处理这些路径,自然不会把JWT过滤器加到Swagger端点上。
内容的提问来源于stack exchange,提问作者Roy Ra
相关产品推荐
相关产品推荐

