无法在 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.
我通过启发 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.