我创建了以下自定义过滤器,用于Spring Cloud应用程序中的授权。这是该过滤器中的apply()
方法,如果授权检查失败,则会引发异常:
@Override
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
HttpStatus status = HttpStatus.FORBIDDEN;
try {
String authRequest = exchange.getRequest().getHeaders().getFirst(
Constants.SESSION_HEADER_NAME);
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> entity = new HttpEntity<String>(authRequest, headers);
// make REST call to authorization module
status = restTemplate.postForEntity(authURL, entity, String.class).getStatusCode();
}
catch (Exception e) {
LOGGER.error("Something went wrong during authorization", e);
}
// throw an exception if anything went
// wrong with authorization
if (!HttpStatus.OK.equals(status)) {
throw new ResponseStatusException(HttpStatus.FORBIDDEN);
}
return chain.filter(exchange);
};
}
我定义了以下@ControllerAdvice
类来捕获上述网关云过滤器引发的所有异常:
@ControllerAdvice
public class RestExceptionHandler {
@ExceptionHandler(value = ResponseStatusException.class)
public final ResponseEntity<Object> handleException(ResponseStatusException ex) {
return new ResponseEntity<>("UNAUTHORIZED", HttpStatus.FORBIDDEN);
}
}
我目前观察到的是以下情况:
ResponseStatusException
不会被@ControllerAdvice
映射方法捕获。@ControllerAdvice
方法捕获。目前,这比阻止程序更令人讨厌,因为实际上从Cloud过滤器中抛出了ResponseStatusException
,并带有自定义错误代码,实际上确实将错误代码返回给了调用者。但是,最好在一个地方处理所有异常。
有人可以阐明这个问题吗?
答案 0 :(得分:0)
带有@ControllerAdvice的类可以显式声明为Spring Bean或通过类路径扫描自动检测。
您没有为过滤器显示完整的类,但是我敢打赌它不是在类路径上扫描的Spring Bean。通常,servlet过滤器显式地插入到Spring Security配置中。因此,ControllerAdvice处理将忽略它。
答案 1 :(得分:0)
我认为“过滤器”是指javax.servlet.Filter
。
在这种情况下,@ControllerAdvice
无法正常工作。它用于处理来自控制器的异常。但是您在Exception甚至无法传播到Controller之前就抛出了异常(通过不调用chain.filter(exchange)
方法。
尝试在控制器而不是过滤器中引发异常。
编辑::如果您不想处理@Controller
上的异常,则必须直接在javax.servlet.Filter
中实现终端处理程序。这意味着可以像这样直接更改传入请求的响应:
HttpServletResponse httpResponse = (HttpServletResponse) exchange.getResponse();
// either format the response by yourself
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
httpResponse.setHeader(...)
...
// or let populate error directly
httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
... @ControllerAdvice
内部执行的操作。