簡體   English   中英

在 WebFilter 類中拋出異常並在 ControllerAdvice 類中處理

[英]Throw an exception in a WebFilter class and handle it in a ControllerAdvice class

我正在嘗試實現一個WebFilter ,它檢查 JWT 並在檢查失敗或結果無效時拋出異常。 我有一個處理這些異常的@ControllerAdvice類。 但它不起作用。

這是WebFilter類:

@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類無法處理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異常處理程序不返回反應類型。 相反,我會定義一個實現ErrorWebExceptionHandler的 bean。 這個處理程序由`spring-webflux 添加到反應流中,所以你不需要擔心優先級。 有關詳細信息,請參閱此答案

我在 webflux 中遇到了同樣的問題,您不想在 webfilter 中拋出直接異常或返回單聲道錯誤),但是您想將響應設置為包含異常的單聲道錯誤(接近您所做的) . 這將允許在請求工作流的正確部分拋出異常,因此它將冒泡到您的其余控制器建議中

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 策略阻止:對預檢請求的響應未通過訪問控制檢查:否“訪問” -Control-Allow-Origin' 標頭存在於請求的資源上。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM