java 无法使用自定义异常处理程序在Sping Boot 中捕获MalformedJwtException

vhmi4jdf  于 2023-03-06  发布在  Java
关注(0)|答案(1)|浏览(216)

我正在使用Sping Boot 3.0.3、Java 17和io.jsonwebtoken v0.11.5。我已经实现了Spring Security,它运行得很好。我想定制的一件事是,当没有传递jwt令牌或传递了错误的jwt令牌时,我会得到一个空的JSON响应,状态403被禁止。我想在该消息中添加一个文本。
因此,我尝试在我的自定义异常处理程序中捕获一个MalformedJwtException,但它没有被捕获。
我有一个JwtAuthenticationFilter类,它从请求标头中提取JWT标记并对其进行验证。如果标记无效,它将抛出MalformedJwtException。我尝试使用try-catch语句并抛出我的自定义异常,但它也没有被捕获。
下面是JwtAuthenticationFilter(方法doFilterInternal)中的相关代码:

try {
  jwt = authHeader.substring(authHeaderStartsWith.length());
  userEmail = jwtService.extractUsername(jwt);
} catch (Exception ex) {
  throw new CustomJWTException("To access this resource, you must provide a valid security token", HttpStatus.UNAUTHORIZED);
}

下面是我的自定义异常处理程序:

@ControllerAdvice
public class GlobalExceptionHandler {
  @ExceptionHandler(value = {CustomException.class})
  public ResponseEntity<ResponseWrapper> handleCustomException(CustomException ex) {
    var response = new ResponseWrapper(ex.getHttpStatus(), ex.getMessage());
   return ResponseEntity.status(ex.getHttpStatus()).body(response);
  }

  @ExceptionHandler(value = {CustomJWTException.class})
  public ResponseEntity<ResponseWrapper> handleCustomJWTException(CustomJWTException ex) {
    var message = ex.getMessage();

    if (message == null || message.isEmpty()) {
      message = "To access this resource, you must provide a valid security token";
    }

    var response = new ResponseWrapper(HttpStatus.UNAUTHORIZED, message);
    return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
  }

  @ExceptionHandler(value = {MalformedJwtException.class})
  public ResponseEntity<ResponseWrapper> handleMalformedJwtException(MalformedJwtException ex) {
    var message = ex.getMessage();

    if (message == null || message.isEmpty()) {
      message = "To access this resource, you must provide a valid security token";
    }

    var response = new ResponseWrapper(HttpStatus.UNAUTHORIZED, message);
    return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
  }
}

我确信doFilterInternal方法中的代码会得到执行并正常工作。此外,我的CustomJWTException也会被抛出(甚至显示在调试控制台中),但由于某种原因,它不会在我的异常处理程序中结束。
我还知道我的异常处理程序工作的事实,因为我抛出的CustomException是其他一些服务,它工作得很好(异常处理程序捕获它)。
我试过调整@Order(有序.最高优先级),但没有任何变化。
我怎样才能达到预期的结果?

exdqitrt

exdqitrt1#

基本上这是因为spring-security和spring-mvc有不同的机制来处理异常。
Spring Security插入了许多过滤器,以便在请求真正命中并由spring-mvc Servlet(即DispatcherServlet)处理之前验证HTTP请求(有关详细信息,请参阅本文)
@ExceptionHandler是spring-mvc的异常处理机制,因此只有在spring-mvc处理请求过程中发生异常时,@ExceptionHandler才会起作用。
现在你的请求已经失败了,并且在spring-mvc处理之前返回到JwtAuthenticationFilter中,这就是@ExceptionHandler不工作的原因。
如何修复取决于您的JwtAuthenticationFilter实现,我通常委托给AuthenticationEntryPoint来处理验证失败时的异常,在AuthenticationEntryPoint中,使用Jackson准备错误响应JSON并返回。

相关问题