我想根据@kopelitsa的答案提供解决方案。主要区别是:
- 通过使用 重用控制器异常处理。
HandlerExceptionResolver
- 使用 Java config over XML config
首先,您需要确保有一个类来处理常规 RestController/Controller(用 ) 注释或 和方法注释的类)中发生的异常。这将处理控制器中发生的异常。下面是使用 RestControllerAdvice 的示例:@RestControllerAdvice
@ControllerAdvice
@ExceptionHandler
@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 安全筛选器链中重用此行为,需要定义一个筛选器并将其挂接到安全配置中。筛选器需要将异常重定向到上述定义的异常处理。下面是一个示例:
@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);
}
}
}
然后,需要将创建的筛选器添加到安全配置中。您需要尽早将其挂接到链中,因为不会捕获前面的所有筛选器的异常。就我而言,在 .请参阅官方文档中的默认筛选器链及其顺序。下面是一个示例: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)
(...)
}
}