我有一个具有Spring Security的弹簧启动1.3.0.BUILD-SNAPSHOT应用程序。我有一个@ControllerAdvice类用于处理来自我的端点的异常,并且运行良好。但是,我无法跟踪Spring Security中的异常,例如AuthenticationException。我使用它来捕获这些异常并记录特定的消息:
@Component
public class MyAuthenticationFailureHandler implements AuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
request.setAttribute(WebAttributes.AUTHENTICATION_EXCEPTION, exception.getLocalizedMessage());
throw new SessionAuthenticationException(exception.getLocalizedMessage());
}
}
即使我有这个例外也从未被捕获:
@ControllerAdvice
public class BaseController {
@ExceptionHandler({SessionAuthenticationException.class})
@ResponseBody
public ResponseEntity getSessionAuthenticationExceptionResponse(Exception exception) {
LOGGER.error("exception.getMessage()", exception);
return ResponseEntity.status( HttpStatus.UNAUTHORIZED )
.contentType( MediaType.APPLICATION_JSON ).body( exception.getLocalizedMessage() );
}
..}
这是我的配置:
@ComponentScan
@EnableAutoConfiguration
@EnableGlobalMethodSecurity(securedEnabled = true)
@SpringBootApplication
public class EDentalManager extends WebMvcConfigurerAdapter {
...
}
和
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterAfter(new CSRFTokenGeneratorFilter(), CsrfFilter.class)
...
.and()
.formLogin()
.loginPage("/loginPage")
.permitAll()
.loginProcessingUrl("/login")
.defaultSuccessUrl("/?tab=success")
.failureHandler(authenticationFailureHandler)
.and()
.logout().addLogoutHandler(logoutHandler).logoutRequestMatcher( new AntPathRequestMatcher("/logout"))
.deleteCookies("JSESSIONID")
.invalidateHttpSession(true).permitAll().and().csrf()
.and()
.sessionManagement()
.withObjectPostProcessor(new AdditionalStrategyPostProcessor(new CleanRegistry(sessionRegistry)))
.sessionFixation().changeSessionId()
.maximumSessions(1)
.maxSessionsPreventsLogin(true)
.expiredUrl("/login?expired" )
.sessionRegistry(sessionRegistry )
.and()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.invalidSessionUrl("/")
.and().authorizeRequests().anyRequest().authenticated();
}
}
捕获Spring Security异常的最佳方法是什么,以便在会话过多,身份验证异常等情况下向用户发送消息?
根据最新发现更新:
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Autowired
private MessageSource messages;
@Autowired
private LocaleResolver localeResolver;
@Override
public void onAuthenticationFailure(final HttpServletRequest request, final HttpServletResponse response,
final AuthenticationException exception) throws IOException, ServletException {
final Locale locale = localeResolver.resolveLocale(request);
String errorMessage = buildErrorMessage(response, exception, locale);
response.setHeader("Authentication Error", errorMessage);
response.setStatus(HttpStatus.UNAUTHORIZED.value());
response.sendError(HttpStatus.UNAUTHORIZED.value(), errorMessage);
}
private void buildErrorMessage(final HttpServletResponse response, Exception exception, Locale locale) {
String errorMessage = messages.getMessage("message.badCredentials", null, locale);
response.setStatus(HttpStatus.UNAUTHORIZED.value());
if (exception instanceof BadCredentialsException) {
errorMessage = messages.getMessage("auth.message.invalid.credentials", null, locale);
} else if (exception.getMessage().equalsIgnoreCase("User is disabled")) {
errorMessage = messages.getMessage("auth.message.disabled", null, locale);
} else if (exception.getMessage().equalsIgnoreCase("User account has expired")) {
errorMessage = messages.getMessage("auth.message.expired", null, locale);
} else if (exception.getMessage().equalsIgnoreCase("blocked")) {
errorMessage = messages.getMessage("auth.message.blocked", null, locale);
} else {
errorMessage = exception.getMessage();
}
}
我的/ login POST后我现在被重定向到error.html,我看到了一个401 ResponseStatus,我有我在响应上的标题信息。
这似乎应该在没有重定向和ResponseEntity的情况下处理,但这并不像Spring Boot&安全处理它。任何人都可以在不使用Thymeleaf(我们是纯粹的http - > json - > Tomcat)的情况下建议更清晰地处理此消息身份验证事件吗?