我想根据@kopelitsa的答案提供解决方案。主要区别在于:
- 通过使用重用控制器异常处理
HandlerExceptionResolver
。
- 在XML配置上使用Java配置
首先,您需要确保有一个类来处理在常规RestController / Controller中发生的异常(用@RestControllerAdvice
或标记的类@ControllerAdvice
和和用标记的方法@ExceptionHandler
)。这可以处理您在控制器中发生的异常。这是使用RestControllerAdvice的示例:
@RestControllerAdvice
public class ExceptionTranslator {
@ExceptionHandler(RuntimeException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public ErrorDTO processRuntimeException(RuntimeException e) {
return createErrorDTO(HttpStatus.INTERNAL_SERVER_ERROR, "An internal server error occurred.", e);
}
private ErrorDTO createErrorDTO(HttpStatus status, String message, Exception e) {
(...)
}
}
要在Spring Security过滤器链中重用此行为,您需要定义一个Filter并将其挂钩到您的安全配置中。筛选器需要将异常重定向到上面定义的异常处理。这是一个例子:
@Component
public class FilterChainExceptionHandler extends OncePerRequestFilter {
private final Logger log = LoggerFactory.getLogger(getClass());
@Autowired
@Qualifier("handlerExceptionResolver")
private HandlerExceptionResolver resolver;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} catch (Exception e) {
log.error("Spring Security Filter Chain Exception:", e);
resolver.resolveException(request, response, null, e);
}
}
}
然后需要将创建的过滤器添加到SecurityConfiguration。您需要非常早地将其挂接到链中,因为不会捕获所有先前过滤器的异常。就我而言,在之前添加它是合理的LogoutFilter
。请参阅官方文档中的默认过滤器链及其顺序。这是一个例子:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@Autowired
private FilterChainExceptionHandler filterChainExceptionHandler;
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.addFilterBefore(filterChainExceptionHandler, LogoutFilter.class)
(...)
}
}