Spring Security 6.x中permitAll搭配addFilterAfter不生效问题
问题分析与解决方案
你遇到的这个问题其实是Spring Security过滤器链的执行逻辑导致的——过滤器的执行优先级在授权规则(比如permitAll)之前。也就是说,不管你给/swagger-ui/**这类路径配置了permitAll,只要你的JWTAuthorizationFilter被加到了过滤器链里,所有请求都会先经过这个过滤器,之后才会走到授权判断的环节。所以即使最终路径会被放行,过滤器还是会先执行一遍,这就是为什么移除过滤器后功能正常的原因。
下面给你几个实用的解决办法:
解决方案1:在JWT过滤器中跳过指定路径
直接修改你的JWTAuthorizationFilter,在核心过滤方法开头添加路径判断,如果是swagger相关路径,直接放行不做校验:
@Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String requestURI = request.getRequestURI(); // 判断是否是swagger相关路径,是的话直接跳过过滤逻辑 if (requestURI.startsWith("/swagger-ui/") || requestURI.startsWith("/v3/api-docs/")) { filterChain.doFilter(request, response); return; } // 原来的JWT校验逻辑 // ... }
解决方案2:为swagger路径单独配置过滤器链
利用Spring Security多过滤器链的特性,给swagger路径配置一个优先级更高的、不带JWT过滤器的链,这样这些请求会先走这个链,不会进入带JWT过滤器的链:
@Configuration @EnableWebSecurity @EnableMethodSecurity public class SecurityConfiguration { public SecurityConfiguration() {} // 优先级更高的链,专门处理swagger路径 @Bean @Order(0) public SecurityFilterChain swaggerFilterChain(HttpSecurity http) throws Exception { http .securityMatcher("/swagger-ui/**", "/v3/api-docs/**") .authorizeHttpRequests(authorize -> authorize .anyRequest().permitAll() ); // 这里不添加JWT过滤器 return http.build(); } @Bean @Order(1) public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .authorizeHttpRequests(authorize -> authorize .anyRequest().authenticated() ) .addFilterAfter(new JWTAuthorizationFilter(), BasicAuthenticationFilter.class); return http.build(); } }
注意这里用了securityMatcher来限定这个链只处理指定路径,而且@Order(0)比原来的@Order(1)优先级更高,所以swagger请求会先走这个链,不会触发JWT过滤器。
解决方案3:限定JWT过滤器的作用路径
如果你不想拆分过滤器链,也可以通过FilterRegistrationBean来注册过滤器,并设置排除swagger路径:
@Bean public FilterRegistrationBean<JWTAuthorizationFilter> jwtFilterRegistration() { FilterRegistrationBean<JWTAuthorizationFilter> registrationBean = new FilterRegistrationBean<>(); registrationBean.setFilter(new JWTAuthorizationFilter()); // 指定过滤器作用于所有路径,排除swagger相关路径 registrationBean.addUrlPatterns("/*"); registrationBean.addExcludeUrlPatterns("/swagger-ui/**", "/v3/api-docs/**"); // 设置过滤器顺序,和原来的addFilterAfter逻辑对齐 registrationBean.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE - 10); return registrationBean; }
不过这种方式需要注意,如果你依赖@EnableWebSecurity自动管理过滤器链,可能需要调整配置逻辑,所以更推荐前两种方案。
内容的提问来源于stack exchange,提问作者piet
相关产品推荐
相关产品推荐

