Spring Boot集成Spring Security时认证失败事件未触发
问题原因
Spring Boot 2.6.x搭配Spring Security时自定义认证失败监听器不触发,核心原因有两个:
- 你在
SecurityConfig中提前注入AuthenticationEventPublisher并手动设置给AuthenticationManagerBuilder时,因为Security配置类加载优先级高于Spring Security自动配置类,拿到的是未完成初始化的代理对象,没有绑定Spring上下文的ApplicationEventPublisher,无法实际推送事件。 - 你的自定义监听器中
LoginAttemptService没有添加依赖注入配置,就算事件触发也会抛出空指针异常。
修复步骤
1. 修复监听器的依赖注入问题
推荐使用构造器注入(Spring 4.3+单构造器无需额外添加@Autowired),避免字段注入导致的空指针:
@Component public class AuthenticationFailureEventListener implements ApplicationListener<AuthenticationFailureBadCredentialsEvent> { private final LoginAttemptService loginAttemptService; public AuthenticationFailureEventListener(LoginAttemptService loginAttemptService) { this.loginAttemptService = loginAttemptService; } @Override public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent e) { WebAuthenticationDetails auth = (WebAuthenticationDetails) e.getAuthentication().getDetails(); loginAttemptService.loginFailed(e.getAuthentication().getName(), auth.getRemoteAddress()); } }
2. 调整安全配置类的事件发布器配置
不要提前注入自动配置的AuthenticationEventPublisher,手动显式定义事件发布器Bean,确保它正确绑定Spring上下文的事件发布组件,同时移除configure(AuthenticationManagerBuilder)中手动设置事件发布器的代码,Spring会自动把容器中的事件发布器绑定到认证管理器:
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private PasswordEncoder passwordEncoder; @Autowired private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler; // 显式定义认证事件发布器,绑定Spring上下文事件推送组件 @Bean public AuthenticationEventPublisher authenticationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { return new DefaultAuthenticationEventPublisher(applicationEventPublisher); } @Override protected void configure(AuthenticationManagerBuilder auth) throws Exception { // 移除手动设置authenticationEventPublisher的代码,Spring会自动装配 auth.userDetailsService(userDetailsService) .passwordEncoder(passwordEncoder); } // 如果你在其他业务逻辑中需要注入使用AuthenticationManager,添加此方法暴露为Bean,否则可省略 @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } // ... 其余HttpSecurity相关配置不变 }
额外注意事项
- 如果你自定义了登录认证过滤器(比如继承
UsernamePasswordAuthenticationFilter),不要在认证逻辑中自行捕获认证异常后直接返回,需要将异常正常抛出到ProviderManager层面,否则无法触发事件发布。 - 配置完成后可以额外添加一个
AuthenticationSuccessEvent的监听器做验证,成功登录时如果能触发成功事件,说明事件发布链路已经正常工作。
内容的提问来源于stack exchange,提问作者robert trudel
相关产品推荐
相关产品推荐

