Spring Boot部分端点OAuth2、部分API Key认证的异常排查
问题解决:添加API Key过滤器后JWT认证端点无需令牌即可访问
问题背景
需要实现三类端点的认证规则:
/secured/**:需Google OAuth2 JWT令牌访问/secured-with-api-key/**:需API Key(含timestamp、signature头)访问/non-secured/**:允许任意访问
未添加ApiKeyAuthFilter时功能正常,但添加后,/secured-with-api-key/**和/non-secured/**表现符合预期,唯独/secured/**无需JWT令牌即可直接访问。
问题原因
在同一个configure(HttpSecurity)方法中多次调用antMatcher()会导致配置冲突:每次调用antMatcher()都会重置当前HttpSecurity的请求匹配规则,后续配置会覆盖前面的规则。同时,oauth2ResourceServer().jwt()的全局配置没有被正确关联到/secured/**的路径规则上,导致JWT认证逻辑未生效。
解决方案
方案1:使用多SecurityFilterChain Bean(推荐Spring Security 5.7+)
将不同路径的安全配置拆分为独立的SecurityFilterChain Bean,每个Bean对应一组路径的认证规则,确保彼此独立生效:
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class AuthConfig { private static final String API_KEY_HEADER_NAME = "API_KEY"; private static final String TIMESTAMP_HEADER_NAME = "timestamp"; private static final String SIGNATURE_HEADER_NAME = "signature"; @Autowired private SimpleAuthenticationManager simpleAuthenticationManager; // 开放/non-secured/**路径 @Bean public SecurityFilterChain nonSecuredFilterChain(HttpSecurity http) throws Exception { http .requestMatchers(matchers -> matchers.antMatchers("/non-secured/**")) .authorizeRequests(auth -> auth.anyRequest().permitAll()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .cors().and().csrf().disable(); return http.build(); } // API Key认证:/secured-with-api-key/** @Bean public SecurityFilterChain apiKeySecuredFilterChain(HttpSecurity http) throws Exception { ApiKeyAuthFilter filter = new ApiKeyAuthFilter(API_KEY_HEADER_NAME, TIMESTAMP_HEADER_NAME, SIGNATURE_HEADER_NAME); filter.setAuthenticationManager(simpleAuthenticationManager); http .requestMatchers(matchers -> matchers.antMatchers("/secured-with-api-key/**")) .addFilter(filter) .authorizeRequests(auth -> auth.anyRequest().authenticated()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .cors().and().csrf().disable() .oauth2ResourceServer().disable(); // 禁用JWT认证,避免干扰 return http.build(); } // JWT认证:/secured/** @Bean public SecurityFilterChain jwtSecuredFilterChain(HttpSecurity http) throws Exception { http .requestMatchers(matchers -> matchers.antMatchers("/secured/**")) .authorizeRequests(auth -> auth.anyRequest().fullyAuthenticated()) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .cors().and().csrf().disable() .oauth2ResourceServer(oauth2 -> oauth2.jwt()); // 启用JWT认证 return http.build(); } }
方案2:兼容旧版本WebSecurityConfigurerAdapter
如果仍需使用WebSecurityConfigurerAdapter,通过and()链式连接不同路径的配置,避免多次调用antMatcher()导致的规则覆盖:
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class AuthConfig extends WebSecurityConfigurerAdapter { private static final String API_KEY_HEADER_NAME = "API_KEY"; private static final String TIMESTAMP_HEADER_NAME = "timestamp"; private static final String SIGNATURE_HEADER_NAME = "signature"; @Autowired private SimpleAuthenticationManager simpleAuthenticationManager; @Override protected void configure(HttpSecurity http) throws Exception { ApiKeyAuthFilter filter = new ApiKeyAuthFilter(API_KEY_HEADER_NAME, TIMESTAMP_HEADER_NAME, SIGNATURE_HEADER_NAME); filter.setAuthenticationManager(simpleAuthenticationManager); http .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) .and() .cors().and().csrf().disable() // 配置开放路径 .authorizeRequests() .antMatchers("/non-secured/**").permitAll() // 配置API Key认证路径 .and() .antMatcher("/secured-with-api-key/**") .addFilter(filter) .authorizeRequests() .antMatchers("/secured-with-api-key/**").authenticated() // 配置JWT认证路径 .and() .antMatcher("/secured/**") .authorizeRequests() .antMatchers("/secured/**").fullyAuthenticated() // 绑定JWT认证逻辑到对应路径 .and() .oauth2ResourceServer().jwt(); } }
关键说明
- 多
SecurityFilterChainBean方式下,Spring Security会根据请求路径自动匹配对应的FilterChain,确保各类认证逻辑互不干扰。 - API Key配置中需禁用
oauth2ResourceServer,防止JWT认证逻辑影响API Key路径;JWT配置中单独启用JWT资源服务器,确保/secured/**路径强制验证JWT令牌。 - 链式配置方式通过
and()分隔不同路径的规则,避免多次重置请求匹配器导致的配置覆盖问题。
内容的提问来源于stack exchange,提问作者John Lai
相关产品推荐
相关产品推荐

