Создайте исключение в классе WebFilter и обработайте его в классе ControllerAdvice. - PullRequest
0 голосов
/ 26 мая 2018

Я пытаюсь реализовать 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);
}

Что вы думаете о проблеме?Вы знаете другой способ реализовать это?

1 Ответ

0 голосов
/ 26 мая 2018

Вы можете попытаться определить @Order() для ваших @ControllerAdvice и @WebFilter бобов и дать @ControllerAdvice более высокий приоритет.

Однако я не думаю, что это путь,Основная причина в том, что обработчики исключений @ControllerAdvice не возвращают реактивные типы.Вместо этого я бы определил бин, который реализует ErrorWebExceptionHandler.Этот обработчик добавляется в реактивный поток с помощью `spring-webflux ', поэтому вам не нужно беспокоиться о приоритете.Подробнее см. этот ответ .

...