在 WebFilter class 中抛出异常并在 ControllerAdvice class 中处理它
Throw an exception in a WebFilter class and handle it in a ControllerAdvice class
我正在尝试实现 WebFilter
检查 JWT 并在检查失败或结果无效时抛出异常。我有一个 @ControllerAdvice
class 来处理这些异常。但是没用。
这是WebFilter
class:
@Component
public class OktaAccessTokenFilter implements WebFilter {
private JwtVerifier jwtVerifier;
@Autowired
public OktaAccessTokenFilter(JwtVerifier jwtVerifier) {
this.jwtVerifier = jwtVerifier;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return Optional.ofNullable(exchange.getRequest().getHeaders().get("Authorization"))
.flatMap(list -> list.stream().findFirst())
.filter(authHeader -> !authHeader.isEmpty() && authHeader.startsWith("Bearer "))
.map(authHeader -> authHeader.replaceFirst("^Bearer", ""))
.map(jwtString -> {
try {
jwtVerifier.decodeAccessToken(jwtString);
} catch (JoseException e) {
throw new DecodeAccessTokenException();
}
return chain.filter(exchange);
}).orElseThrow(() -> new AuthorizationException());
}
}
以及异常处理程序:
@ControllerAdvice
public class SecurityExceptionHandler {
@ExceptionHandler(AuthorizationException.class)
public ResponseEntity authorizationExceptionHandler(AuthorizationException ex) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
@ExceptionHandler(DecodeAccessTokenException.class)
public ResponseEntity decodeAccessTokenExceptionHandler(DecodeAccessTokenException ex) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
我认为,@ControllerAdvice
class 无法处理 WebFilter
抛出的异常。因为,如果我将异常移至控制器,它就可以工作。
我已经为此更改了代码(现在):
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Optional<String> authJwt = Optional.ofNullable(exchange.getRequest().getHeaders().get("Authorization"))
.flatMap(list -> list.stream().findFirst())
.filter(authHeader -> !authHeader.isEmpty() && authHeader.startsWith("Bearer "))
.map(authHeader -> authHeader.replaceFirst("^Bearer", ""));
if (authJwt.isPresent()) {
String jwtString = authJwt.get();
try {
jwtVerifier.decodeAccessToken(jwtString);
} catch (JoseException e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().writeWith(Mono.empty());
}
} else {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().writeWith(Mono.empty());
}
return chain.filter(exchange);
}
你觉得这个问题怎么样?你知道另一种实现方式吗?
您可以尝试为 @ControllerAdvice
和 @WebFilter
bean 定义一个 @Order()
,并赋予 @ControllerAdvice
更高的优先级。
但是,我不认为这是要走的路,主要原因是 @ControllerAdvice
异常处理程序没有 return 反应类型。相反,我会定义一个实现 ErrorWebExceptionHandler
的 bean。此处理程序由 `spring-webflux 添加到反应流中,因此您无需担心优先级。有关详细信息,请参阅 。
我在 webflux 中遇到了同样的问题,你不想在 webfilter 中抛出直接异常或 return 单声道错误),但是你想将响应设置为包含异常(接近你所做的)。这将允许在请求工作流的正确部分抛出异常,因此它将冒泡到您的其余控制器建议
public class YourFilter implements WebFilter{
@Override
public Mono<Void> filter(final ServerWebExchange exchange, final WebFilterChain chain){
exchange.getResponse().writeWith(Mono.error(new YouException()));
return chain.filter(exchange);
}
}
我试过了,但出现 CORS 错误
这是错误:
从来源 'http://localhost:4200' 访问 'http://localhost:8084/users/files' 处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:否 'Access-Control-Allow-Origin' header 出现在请求的资源上。
我正在尝试实现 WebFilter
检查 JWT 并在检查失败或结果无效时抛出异常。我有一个 @ControllerAdvice
class 来处理这些异常。但是没用。
这是WebFilter
class:
@Component
public class OktaAccessTokenFilter implements WebFilter {
private JwtVerifier jwtVerifier;
@Autowired
public OktaAccessTokenFilter(JwtVerifier jwtVerifier) {
this.jwtVerifier = jwtVerifier;
}
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
return Optional.ofNullable(exchange.getRequest().getHeaders().get("Authorization"))
.flatMap(list -> list.stream().findFirst())
.filter(authHeader -> !authHeader.isEmpty() && authHeader.startsWith("Bearer "))
.map(authHeader -> authHeader.replaceFirst("^Bearer", ""))
.map(jwtString -> {
try {
jwtVerifier.decodeAccessToken(jwtString);
} catch (JoseException e) {
throw new DecodeAccessTokenException();
}
return chain.filter(exchange);
}).orElseThrow(() -> new AuthorizationException());
}
}
以及异常处理程序:
@ControllerAdvice
public class SecurityExceptionHandler {
@ExceptionHandler(AuthorizationException.class)
public ResponseEntity authorizationExceptionHandler(AuthorizationException ex) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
@ExceptionHandler(DecodeAccessTokenException.class)
public ResponseEntity decodeAccessTokenExceptionHandler(DecodeAccessTokenException ex) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
}
}
我认为,@ControllerAdvice
class 无法处理 WebFilter
抛出的异常。因为,如果我将异常移至控制器,它就可以工作。
我已经为此更改了代码(现在):
@Override
public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
Optional<String> authJwt = Optional.ofNullable(exchange.getRequest().getHeaders().get("Authorization"))
.flatMap(list -> list.stream().findFirst())
.filter(authHeader -> !authHeader.isEmpty() && authHeader.startsWith("Bearer "))
.map(authHeader -> authHeader.replaceFirst("^Bearer", ""));
if (authJwt.isPresent()) {
String jwtString = authJwt.get();
try {
jwtVerifier.decodeAccessToken(jwtString);
} catch (JoseException e) {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().writeWith(Mono.empty());
}
} else {
exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
return exchange.getResponse().writeWith(Mono.empty());
}
return chain.filter(exchange);
}
你觉得这个问题怎么样?你知道另一种实现方式吗?
您可以尝试为 @ControllerAdvice
和 @WebFilter
bean 定义一个 @Order()
,并赋予 @ControllerAdvice
更高的优先级。
但是,我不认为这是要走的路,主要原因是 @ControllerAdvice
异常处理程序没有 return 反应类型。相反,我会定义一个实现 ErrorWebExceptionHandler
的 bean。此处理程序由 `spring-webflux 添加到反应流中,因此您无需担心优先级。有关详细信息,请参阅
我在 webflux 中遇到了同样的问题,你不想在 webfilter 中抛出直接异常或 return 单声道错误),但是你想将响应设置为包含异常(接近你所做的)。这将允许在请求工作流的正确部分抛出异常,因此它将冒泡到您的其余控制器建议
public class YourFilter implements WebFilter{
@Override
public Mono<Void> filter(final ServerWebExchange exchange, final WebFilterChain chain){
exchange.getResponse().writeWith(Mono.error(new YouException()));
return chain.filter(exchange);
}
}
我试过了,但出现 CORS 错误 这是错误:
从来源 'http://localhost:4200' 访问 'http://localhost:8084/users/files' 处的 XMLHttpRequest 已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:否 'Access-Control-Allow-Origin' header 出现在请求的资源上。