Spring Security5.7弃用适配器后如何配置AuthenticationProvider
首先明确一个基础认知:WebSecurityCustomizer 仅用于配置完全绕过Spring Security过滤器链的路径,通常只放静态资源、服务健康检查这类完全不需要安全管控的路径,和认证逻辑接入、接口授权规则配置没有关联。
Spring Security 5.7版本弃用WebSecurityConfigurerAdapter的核心设计思路是将所有安全配置转向Spring Bean注册模式,自定义Authentication Provider不需要像旧版本一样手动注入到AuthenticationManagerBuilder中,只要将Provider实现类注册为Spring容器托管的Bean,框架会自动收集所有Provider并接入全局认证流程。
具体实现步骤
1. 编写自定义AuthenticationProvider
实现AuthenticationProvider接口,在authenticate方法中编写你的REST API认证逻辑,类上加@Component注解交给Spring管理即可,以下是常见的用户名密码认证Provider示例:
@Component public class CustomRestAuthProvider implements AuthenticationProvider { private final UserDetailsService userDetailsService; private final PasswordEncoder passwordEncoder; // 构造注入依赖,可根据你的业务需求替换为自己的用户查询、校验服务 public CustomRestAuthProvider(UserDetailsService userDetailsService, PasswordEncoder passwordEncoder) { this.userDetailsService = userDetailsService; this.passwordEncoder = passwordEncoder; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { // 从认证请求中获取提交的凭证 String username = authentication.getName(); String inputPassword = (String) authentication.getCredentials(); // 自定义校验逻辑:查询用户、比对密码、校验账号状态等 UserDetails userDetail = userDetailsService.loadUserByUsername(username); if (!passwordEncoder.matches(inputPassword, userDetail.getPassword())) { throw new BadCredentialsException("用户名或密码错误"); } if (!userDetail.isEnabled()) { throw new DisabledException("账号已被禁用"); } // 认证通过后,返回填充了权限信息的已认证Authentication对象 return new UsernamePasswordAuthenticationToken( userDetail, null, userDetail.getAuthorities() ); } @Override public boolean supports(Class<?> authType) { // 声明当前Provider支持的认证类型,示例为支持用户名密码认证 return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authType); } }
2. 配置SecurityFilterChain定义接口安全规则
旧版本中重写configure(HttpSecurity http)实现的所有接口权限、过滤器、登录登出配置,现在全部迁移到SecurityFilterChainBean中声明,你之前写的WebSecurityCustomizer配置可以直接保留:
@EnableWebSecurity @Configuration public class SecurityConfig { // 原有全局忽略配置保留即可,注意不要把需要权限校验的业务接口放这里 @Bean public WebSecurityCustomizer webSecurityCustomizer() { return (web) -> web.ignoring() .antMatchers("/users/getUser"); } // 替代旧版本HttpSecurity配置的核心Bean @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http // REST API前后端分离场景通常关闭CSRF防护 .csrf().disable() // 配置接口访问权限规则 .authorizeHttpRequests(auth -> auth // 配置允许匿名访问的公开接口 .antMatchers("/auth/login", "/public/**").permitAll() // 其余所有接口都需要认证后访问 .anyRequest().authenticated() ) // 关闭默认的表单跳转登录,适配REST API返回JSON的需求 .formLogin().disable() .httpBasic(); // 如果需要添加JWT校验过滤器、自定义登录过滤器等,在这里通过http.addFilterBefore/After方法添加即可 return http.build(); } // 注册密码编码器为Bean,供Provider使用 @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } }
3. 可选配置:暴露AuthenticationManager实例
如果你的登录逻辑是在自定义Controller中手动触发认证(比如前后端分离项目自定义登录接口返回JSON结果),只需要在配置类中注册AuthenticationManagerBean,就可以直接注入到业务代码中使用:
@Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); }
常见踩坑说明
- 不要将需要权限控制的业务接口加入
WebSecurityCustomizer的ignoring列表,加入该列表的路径会完全绕过Spring Security过滤器链,所有认证、权限注解都不会生效 - 如果需要支持多种认证方式(比如同时支持账号密码、短信验证码、第三方Token认证),只需要编写多个
AuthenticationProvider实现类,全部注册为Spring Bean即可,框架会自动根据每个Provider的supports()方法匹配对应的认证请求 - 多Provider场景下如果需要指定认证顺序,可以在Provider类上加
@Order注解调整优先级
内容的提问来源于stack exchange,提问作者Mr.DevEng

