我们正在将Spring Cloud Gateway与Spring Boot 2和反应式WebFlux模块一起使用。
为其中一个路由添加了身份验证过滤器。现在,如果我们抛出一个带有特定状态代码的 RuntimeException,它实际上不会拾取。
早些时候,此身份验证检查是 Spring 中 HandlerInterceptor 的一部分,但现在我们不能将 Web 模块与 WebFlux 一起使用(来自 Spring 云网关的冲突(。
例:
@Override
public GatewayFilter apply(Object config) {
ServerHttpRequest httpRequest = exchange.getRequest();
if(!someUtil.validRequest(httpRequest) {
throw new RuntimeException("Throw 401 Unauthorized with Custom error code and message");
}
}
目前,实际响应始终给出500 内部服务器错误。这是从哪里来的?我们可以在这里掌握过滤器的错误吗?
您可以实现自定义错误处理程序,这里是 Spring Boot 文档。
或者你可以简单地抛出一个 ResponseStatusException。默认错误处理程序将呈现特定状态。
请记住,在撰写本文时,spring-cloud-gateway使用Spring Framework WebFlux。这意味着方法会有所不同。您可以在筛选器中获取异常,如下所示。
声明如下异常:
public class UnauthorisedException extends ResponseStatusException {
public UnauthorisedException(HttpStatusCode status) {
super(status);
}
public UnauthorisedException(HttpStatusCode status, String reason) {
super(status, reason);
}
}
注意:异常扩展了 ResponseStatusException。
ControllerAdvice 类可以按如下方式实现:
@ControllerAdvice
public class MyErrorWebExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(UnauthorisedException.class)
public Mono<ServerResponse> handleIllegalState(ServerWebExchange exchange, UnauthorisedException exc) {
exchange.getAttributes().putIfAbsent(ErrorAttributes.ERROR_ATTRIBUTE, exc);
return ServerResponse.from(ErrorResponse.builder(exc,HttpStatus.FORBIDDEN,exc.getMessage()).build());
}
}
在筛选器中,现在可以实现apply
方法,如下所示:
public GatewayFilter apply(Config config) {
return (exchange, chain) -> {
ServerHttpRequest request = exchange.getRequest();
if (request.getHeaders().get("token") == null){ //test is an example
throw new UnauthorisedException(HttpStatus.FORBIDDEN, "Not Authorised from Gateway");
}
ServerHttpRequest.Builder builder = request.mutate();
return chain.filter(exchange.mutate().request(builder.build()).build());
};
}