我正在使用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(有序.最高优先级),但没有任何变化。
我怎样才能达到预期的结果?
1条答案
按热度按时间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并返回。