如何在WebSecurityConfigurerAdapter中同时配置Basic认证与OAuth2?
问题原因
日志中明确抛出ProviderNotFoundException: No AuthenticationProvider found for org.springframework.security.authentication.UsernamePasswordAuthenticationToken,根因是当你显式配置了OAuth2资源服务器的JWT认证后,Spring Security自动配置会跳过默认的用户名密码认证相关Provider注册,导致Basic认证流程提取到账号密码凭证后,没有对应的处理器完成认证。
解决方案
方案1:现有配置补充认证Provider(改动最小)
直接在你当前的配置类中注册处理用户名密码的认证Provider即可:
@Configuration public class JWTSecurityConfig extends WebSecurityConfigurerAdapter { // 注册内存用户,对应你配置的test/test @Bean public UserDetailsService userDetailsService() { UserDetails user = User.withUsername("test") // {noop}标识明文密码,生产环境替换为加密后的密码和对应编码器 .password("{noop}test") .authorities("ROLE_USER") .build(); return new InMemoryUserDetailsManager(user); } // 注册处理用户名密码认证的Provider @Bean public AuthenticationProvider daoAuthenticationProvider() { DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); authProvider.setUserDetailsService(userDetailsService()); return authProvider; } @Override protected void configure(HttpSecurity http) throws Exception { http // 注册自定义的Provider .authenticationProvider(daoAuthenticationProvider()) .authorizeRequests(authz -> authz .antMatchers(HttpMethod.GET, "/jwt").hasAuthority("SCOPE_email") .antMatchers(HttpMethod.GET, "/basic").authenticated() .anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.jwt()) .httpBasic() .and() .csrf().disable(); } }
方案2:拆分独立安全配置(更推荐,隔离性更强)
为两类接口分别创建独立的安全配置,完全隔离认证逻辑,避免后续再出现冲突:
Basic认证配置(优先级更高,仅处理/basic路径)
@Configuration @Order(1) public class BasicSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http // 只匹配/basic路径 .antMatcher("/basic") .authorizeRequests(authz -> authz.anyRequest().authenticated()) .httpBasic() .and() .csrf().disable(); } @Bean public UserDetailsService basicUserDetailsService() { UserDetails user = User.withUsername("test") .password("{noop}test") .authorities("ROLE_USER") .build(); return new InMemoryUserDetailsManager(user); } }
JWT认证配置(处理除/basic外的所有路径)
@Configuration @Order(2) public class JWTSecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .authorizeRequests(authz -> authz .antMatchers(HttpMethod.GET, "/jwt").hasAuthority("SCOPE_email") .anyRequest().authenticated()) .oauth2ResourceServer(oauth2 -> oauth2.jwt()) .csrf().disable(); } }
注意事项
- 示例中使用
{noop}标识明文密码仅为适配你的现有配置,生产环境请使用BCryptPasswordEncoder等加密器存储密码,避免明文泄露风险。 - 你当前使用的
WebSecurityConfigurerAdapter在Spring Security 5.7及以上版本已被标记为废弃,后续升级版本可以替换为SecurityFilterChainBean的配置方式。
内容的提问来源于stack exchange,提问作者codesmith
相关产品推荐
相关产品推荐

