无法在 Java 中捕获异常

Cannot catch Exception in Java

我通过启发 Baeldung 的 Prevent Brute Force Authentication Attempts with Spring Security 页面:

为我的登录服务实施了暴力破解机制,如下所示
@Service
@RequiredArgsConstructor
public class LoginServiceImpl implements LoginService {

    private final UserService userService;
    private final LoginAttemptService loginAttemptService;

    public UserTokenDTO login(final LoginRequest request) {        

        if(!user.isValid) {
            throw new InvalidCredentialsException();
        }
        // code omitted for brevity
    }
}

当用户未通过验证时,LoginService 抛出 InvalidCredentialsException() 然后我试图在 AuthenticationFailureListener class:

中捕获此异常
@Component
public class AuthenticationFailureListener implements 
    ApplicationListener<AuthenticationFailureBadCredentialsEvent> {

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private LoginAttemptService loginAttemptService;

    @Override
    public void onApplicationEvent(final AuthenticationFailureBadCredentialsEvent e) {
        final String xfHeader = request.getHeader("X-Forwarded-For");
        if (xfHeader == null) {
            loginAttemptService.loginFailed(request.getRemoteAddr());
        } else {
            loginAttemptService.loginFailed(xfHeader.split(",")[0]);
        }
    }
}

当出现错误时,会调用loginAttemptService.loginFailed()方法。但是,我无法在 onApplicationEvent() 中捕获异常。我尝试过使用不同的事件类型,但对于某些事件,例如ApplicationEvent 它在每个事件上触发,我应该只在抛出 InvalidCredentialsException 时用户未通过身份验证时触发它。

搜索后,我发现我需要进行配置,以便 Spring 安全在失败或成功时捕获这些事件。但是定义不明确,我想也许我可以通过在 AuthenticationFailureListener class 中使用正确的事件类型来捕获事件。我也有一个事件处理程序 class,但我不确定它是否有帮助。

更新: 这是我的SecurityConfig。我仍然无法触发 AuthenticationFailureBadCredentialsEvent 并且无法得到任何异常 onApplicationEvent.

@EnableWebSecurity
@AllArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    AuthenticationFailureHandler eventAuthenticationFailureHandler() {
        return new CustomAuthenticationFailureHandler();
    }

    private final AuthenticationFailureHandler eventAuthenticationFailureHandler;

    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .formLogin().failureHandler(eventAuthenticationFailureHandler)
                .and()
                .httpBasic();
    }
}

中所写:

If authentication is successful, an InteractiveAuthenticationSuccessEvent will be published via the application context. No events will be published if authentication was unsuccessful, because this would generally be recorded via an AuthenticationManager-specific application event.