我有一个使用Jersey作为JAX-RS实现的Spring Boot应用程序。这是我的安全配置:
@Configuration @EnableGlobalMethodSecurity(prePostEnabled = true) @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired TokenAuthenticationProvider tokenAuthenticationProvider; @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.authenticationProvider(tokenAuthenticationProvider); } @Override protected void configure(HttpSecurity http) throws Exception { http.addFilterBefore(new AuthenticationTokenFilter(), BasicAuthenticationFilter.class) .csrf().disable() .authorizeRequests() .antMatchers("/dataHub/**") .authenticated(); } }
我想要做的是有一种方法来捕获我的TokenAuthenticationProvider抛出的异常,并将其转换为我们已经同意的标准化JSON格式。有没有办法做到这一点?我尝试添加自定义AuthenticationFailureHandler,但无法正常工作。
WebSecurityConfigurerAdapter方法
的HttpSecurity类有一个叫做方法exceptionHandling可用于覆盖默认行为。以下示例介绍了如何自定义响应消息。
HttpSecurity
@Override protected void configure(HttpSecurity http) throws Exception { http // your custom configuration goes here .exceptionHandling() .authenticationEntryPoint((request, response, e) -> { String json = String.format("{\"message\": \"%s\"}", e.getMessage()); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); response.setContentType("application/json"); response.setCharacterEncoding("UTF-8"); response.getWriter().write(json); }); }
@ControllerAdvice方法-为什么在这种情况下不起作用
最初,我想到的@ControllerAdvice是捕获整个应用程序的身份验证异常。
@ControllerAdvice
import org.springframework.http.HttpStatus; import org.springframework.security.core.AuthenticationException; @ControllerAdvice public class AuthExceptionHandler { @ResponseStatus(HttpStatus.UNAUTHORIZED) @ExceptionHandler(AuthenticationException.class) @ResponseBody public String handleAuthenticationException(AuthenticationException e) { return String.format("{\"message\": \"%s\"}", e.getMessage()); } }
在上面的示例中,JSON是手动构建的,但是您可以简单地返回一个POJO,该POJO将被映射到JSON中,就像从常规REST控制器中一样。既然Spring 4.3,你也可以使用@RestControllerAdvice,这是一个组合@ControllerAdvice和@ResponseBody。
@ResponseBody
但是,这种方法行不通, 因为在到达任何控制器之前,该异常将由抛出AbstractSecurityInterceptor并由ExceptionTranslationFilter处理。
AbstractSecurityInterceptor