Spring Security弃用WebSecurityConfigurerAdapter后数据库认证配置
核心结论
你不需要再保留旧版基于WebSecurityConfigurerAdapter重写configure(AuthenticationManagerBuilder auth)的代码,在新版Spring Security(5.7+正式废弃适配器类)中,基于Bean的组件化配置会自动完成认证提供者的注册。
原因说明
Spring Security 从5.4版本开始就推荐脱离继承适配器的配置方式:只要你将自定义的DaoAuthenticationProvider声明为Spring容器管理的@Bean,Spring Security的自动配置逻辑会自动收集容器中所有AuthenticationProvider类型的Bean,将其注册到全局认证管理器AuthenticationManager中,无需手动通过AuthenticationManagerBuilder添加。
两种可用配置方式
1. 最简配置(推荐)
直接删除ApplicationSecurityConfig中残留的旧版configure方法即可,其余代码无需改动,你已经声明的daoAuthenticationProvider() Bean会被自动识别加载。
修正后精简的安全配置类结构如下:
@Configuration @EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class ApplicationSecurityConfig { private final PasswordEncoder passwordEncoder; private final ApplicationUserService userService; public ApplicationSecurityConfig(PasswordEncoder passwordEncoder,ApplicationUserService userService) { this.passwordEncoder = passwordEncoder; this.userService = userService; } @Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .csrf().disable() .authorizeRequests() .antMatchers("/", "index", "/css/*", "/js/*").permitAll() .antMatchers("/api/**").hasRole(STUDENT.name()) .anyRequest() .authenticated() .and() .formLogin() .loginPage("/login") .permitAll() .defaultSuccessUrl("/courses", true) .passwordParameter("password") .usernameParameter("username") .and() .rememberMe() .tokenValiditySeconds((int) TimeUnit.DAYS.toSeconds(21)) .key("example") .rememberMeParameter("remember-me") .and() .logout() .logoutUrl("/logout") .logoutRequestMatcher(new AntPathRequestMatcher("/logout", "GET")) .clearAuthentication(true) .invalidateHttpSession(true) .deleteCookies("JSESSIONID", "remember-me") .logoutSuccessUrl("/login"); return http.build(); } // 这个Bean保留,会被自动注册到认证管理器 @Bean public DaoAuthenticationProvider daoAuthenticationProvider() { DaoAuthenticationProvider provider = new DaoAuthenticationProvider(); provider.setPasswordEncoder(passwordEncoder); provider.setUserDetailsService(userService); return provider; } // 直接删除旧的configure(AuthenticationManagerBuilder auth)方法即可 }
2. 显式配置(多认证场景推荐)
如果后续你需要添加多个认证方式(比如短信验证码登录、LDAP认证),或者希望显式指定认证提供者的加载顺序,可以直接在HttpSecurity配置中手动注册Provider,不需要依赖自动收集,配置方式如下:
@Bean protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http // 显式注册自定义DAO认证提供者,多个Provider按添加顺序执行认证 .authenticationProvider(daoAuthenticationProvider()) .csrf().disable() // 后续拦截、登录、登出等配置和之前完全一致 .authorizeRequests() // ... 其余原有配置保持不变 return http.build(); }
需要修复的代码问题
你当前代码中存在一个会直接导致认证失败的参数顺序错误:FakeApplicationUserDaoService中实例化ApplicationUser时,用户名和密码的传参顺序和类构造函数定义的顺序不匹配。ApplicationUser构造函数前两个参数顺序为(String password, String username),但你实例化时先传了用户名、后传了密码,需要修正传参顺序:
new ApplicationUser( passwordEncoder.encode("password"), // 第一个参数传密码 "annasmith", // 第二个参数传用户名 STUDENT.getGrantedAuthorities(), true, true, true, true ) // linda、tom两个用户的实例化传参也需要按这个顺序调整
内容的提问来源于stack exchange,提问作者iank

