Spring Security从5升级到6后出现空指针异常求助
Spring Security 5→6.0迁移后AuthenticationManager空指针问题解决
问题重现
迁移后触发空指针异常:
java.lang.NullPointerException: Cannot invoke "org.springframework.security.authentication.AuthenticationManager.authenticate(org.springframework.security.core.Authentication)" because the return value of "org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.getAuthenticationManager()" is null at com.jmi.jabord.core.oauth.filter.AccessTokenAuthenticationFilter.attemptAuthentication(AccessTokenAuthenticationFilter.java:79) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:231) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:221) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:107) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:93) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
已尝试在自定义AccessTokenAuthenticationFilter中添加如下代码,但未解决问题:
@Autowired @Qualifier("authenticationManager") @Override public void setAuthenticationManager(AuthenticationManager authenticationManager) { super.setAuthenticationManager(authenticationManager); }
解决方案
1. 在SecurityFilterChain中显式注入AuthenticationManager
Spring Security 6不再自动全局暴露AuthenticationManager,需在配置类中通过AuthenticationConfiguration获取并手动注入到自定义Filter:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationConfiguration authConfig) throws Exception { // 获取AuthenticationManager实例 AuthenticationManager authenticationManager = authConfig.getAuthenticationManager(); // 初始化自定义Filter并设置AuthenticationManager AccessTokenAuthenticationFilter tokenFilter = new AccessTokenAuthenticationFilter(); tokenFilter.setAuthenticationManager(authenticationManager); // 将Filter加入过滤器链 http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); // 其他安全配置... return http.build(); } }
2. 确保自定义Filter被Spring容器管理(若用@Component)
如果你的AccessTokenAuthenticationFilter标注了@Component,需直接注入容器中的实例而非新建对象:
@Configuration @EnableWebSecurity public class SecurityConfig { @Autowired private AccessTokenAuthenticationFilter tokenFilter; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationConfiguration authConfig) throws Exception { AuthenticationManager authenticationManager = authConfig.getAuthenticationManager(); tokenFilter.setAuthenticationManager(authenticationManager); http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); // 其他安全配置... return http.build(); } }
3. 校验AuthenticationManager的Bean名称
确认你的AuthenticationManagerBean名称确实为authenticationManager,若自定义了认证提供者,需保证配置正确:
@Bean public AuthenticationManager authenticationManager(AuthenticationConfiguration config) throws Exception { return config.getAuthenticationManager(); }
如果Bean名称不是authenticationManager,需同步修改@Qualifier的参数值。
4. 通过构造方法注入AuthenticationManager(更可靠)
Spring Security 6中Filter初始化顺序可能变化,构造方法注入能避免时机问题:
@Component public class AccessTokenAuthenticationFilter extends AbstractAuthenticationProcessingFilter { // 构造方法直接注入AuthenticationManager public AccessTokenAuthenticationFilter(AuthenticationManager authenticationManager) { super(new AntPathRequestMatcher("/api/**")); // 替换为你的请求匹配路径 super.setAuthenticationManager(authenticationManager); } // 实现attemptAuthentication方法... }
配置类中直接注入该Filter即可:
@Autowired private AccessTokenAuthenticationFilter tokenFilter; @Bean public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.addFilterBefore(tokenFilter, UsernamePasswordAuthenticationFilter.class); // 其他安全配置... return http.build(); }
内容的提问来源于stack exchange,提问作者Shivamurugan S
相关产品推荐
相关产品推荐

