Spring Security中SecurityFilterChain同时支持Basic Auth与OAuth的问题
SecurityFilterChain无法同时启用Basic Auth与OAuth2资源服务器
问题描述
原使用WebSecurityConfigurerAdapter实现的Spring Boot OAuth认证应用可同时支持Basic授权与OAuthResourceServer,但改用SecurityFilterChain Bean后,仅能生效最后配置的Basic Auth或OAuthResourceServer其中一种。
用户配置代码如下:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception{ http.csrf().disable(); http.authorizeRequests().anyRequest().authenticated().and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS); if(this.credentials.isEnabled()){ http.httpBasic().authenticationEntryPoint(new RestAuthenticationEntryPoint()); } if(this.credentials.isOauthEnabled()){ http.oauth2ResourceServer().jwt(); } return http.build(); }
日志分析
从TRACE日志可见,系统生成了两个独立的DefaultSecurityFilterChain:
- 第一个过滤器链仅包含
BearerTokenAuthenticationFilter - 第二个过滤器链同时包含
BearerTokenAuthenticationFilter与BasicAuthenticationFilter
Spring Security会按顺序匹配过滤器链,第一个匹配的链会处理请求,导致只有其中一种认证方式生效。
解决方案
核心是在同一个SecurityFilterChain中合并两种认证配置,并配置AuthenticationManager以支持多种认证类型,确保Spring Security能根据请求自动选择合适的认证方式。
修改后的配置代码
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { http.csrf().disable() // 配置无状态会话 .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) // 所有请求需认证 .authorizeRequests(auth -> auth.anyRequest().authenticated()) // 配置Basic Auth的异常入口 .httpBasic(basic -> basic.authenticationEntryPoint(new RestAuthenticationEntryPoint())) // 配置OAuth2资源服务器JWT认证 .oauth2ResourceServer(oauth2 -> oauth2.jwt()) // 注入AuthenticationManager,支持多种认证类型 .authenticationManager(authenticationManager); return http.build(); } // 暴露默认AuthenticationManager(若未自定义) @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); }
保留开关逻辑的版本
若需保留原有的开关配置,可调整为:
@Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManager authenticationManager) throws Exception { http.csrf().disable() .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .authorizeRequests(auth -> auth.anyRequest().authenticated()) .authenticationManager(authenticationManager); if(this.credentials.isEnabled()){ http.httpBasic(basic -> basic.authenticationEntryPoint(new RestAuthenticationEntryPoint())); } if(this.credentials.isOauthEnabled()){ http.oauth2ResourceServer(oauth2 -> oauth2.jwt()); } return http.build(); } @Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception { return authConfig.getAuthenticationManager(); }
关键说明
- 确保所有认证配置都添加到同一个
HttpSecurity实例,避免生成多个独立的过滤器链 - 注入
AuthenticationManager,让Spring Security能够同时处理Basic认证与JWT认证请求 - Spring Security会根据请求头自动选择认证方式:带
Authorization: Basic ...走Basic认证,带Authorization: Bearer ...走JWT认证
内容的提问来源于stack exchange,提问作者soham pathak
相关产品推荐
相关产品推荐

