多SecurityFilterChain中hasAuthority("ADMIN")权限校验失效问题
问题根源
Spring Security 中多个SecurityFilterChain是按@Order注解的数值从小到大顺序执行的,第一个匹配到当前请求的FilterChain会完全处理该请求,后续FilterChain不会再介入。
你遇到的问题核心在于:
- 优先级更高的
apiKeyFilterChain(@Order(1))中配置了requestMatchers("/admin/**").permitAll(),所有/admin/notification/**这类请求会被第一个FilterChain直接放行,根本不会流转到jwtFilterChain(@Order(2))执行权限校验。 - 你在
ApiKeyAuthFilter中配置的shouldNotFilter只是让过滤器不执行,但FilterChain的授权规则已经生效,请求依然会被第一个FilterChain允许访问。
解决方案
需要给两个FilterChain明确划分各自负责的路径范围,确保需要JWT权限校验的路径不会被第一个FilterChain提前处理。
1. 修改apiKeyFilterChain,限定仅处理需要API Key验证的路径
假设你的API Key仅用于/external/**这类外部接口(根据实际业务调整),修改后代码如下:
@Bean @Order(1) public SecurityFilterChain apiKeyFilterChain(HttpSecurity http) throws Exception { http // 明确指定此FilterChain仅处理的路径 .requestMatchers(matchers -> matchers.antMatchers("/external/**")) .csrf(AbstractHttpConfigurer::disable) .cors(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth .anyRequest().authenticated() ) .httpBasic(Customizer.withDefaults()) .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authenticationProvider(authenticationProvider) .addFilterBefore(apiKeyAuthFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); }
2. 调整jwtFilterChain,明确处理剩余路径并保留权限规则
@Bean @Order(2) public SecurityFilterChain jwtFilterChain(HttpSecurity http) throws Exception { http // 指定此FilterChain处理的路径范围 .requestMatchers(matchers -> matchers .antMatchers("/admin/**", "/auth/**", "/clients/**") ) .csrf(AbstractHttpConfigurer::disable) .authorizeHttpRequests(auth -> auth .requestMatchers(new AntPathRequestMatcher("/admin/notification/**")).hasAuthority("ADMIN") .requestMatchers(new AntPathRequestMatcher("/auth/**")).permitAll() .requestMatchers(new AntPathRequestMatcher("/clients/**")).permitAll() .requestMatchers(new AntPathRequestMatcher("/admin/**")).authenticated() .anyRequest().authenticated() ) .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authenticationProvider(authenticationProvider) .addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class); return http.build(); }
3. 可选:移除ApiKeyAuthFilter中的排除路径逻辑
现在FilterChain已经明确划分了路径范围,ApiKeyAuthFilter只会在/external/**路径下执行,无需再通过shouldNotFilter排除其他路径,可以删除这部分代码。
内容的提问来源于stack exchange,提问作者yhab shaker
相关产品推荐
相关产品推荐

