В настоящее время я нахожусь в процессе разработки REST-Api с помощью Springboot. После запуска и запуска моего пользовательского JwtAuthenticationPrivider я заметил, что исключения, связанные с JWT, которые могут возникнуть при синтаксическом анализе токена, обрабатываются неправильно.
401 отправляется обратно клиенту, но исключение отображается как ошибка в журналах, что не является правильным в моих глазах. Это явно ошибка клиента, и ее не следует указывать как ошибку в журнале сервера.
2020-04-02 13:43:26.616 ERROR 1666943 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception
io.jsonwebtoken.security.SignatureException: JWT signature does not match locally computed signature. JWT validity cannot be asserted and should not be trusted.
Поскольку я уже использую ResponseEntityExceptionHandler для исключений обработчика, было бы хорошо используйте его и для цепочки фильтров. Я знаю, что аннотация @ ExceptionHandler работает только с обработчиками.
Но поскольку они создают только объект ResponseEntity , я мог бы использовать эти методы для создания сообщений об ошибках для цепочка фильтров.
Мне трудно найти пружинный идиоматический c способ.
Моя первая идея заключается в следующем:
public class JwtAuthorizationFilter extends OncePerRequestFilter {
...
@Override
protected void doFilterInternal(HttpServletRequest req, HttpServletResponse res, FilterChain chain)
throws IOException, ServletException {
try {
String header = req.getHeader(AUTHORIZATION_HEADER);
if (header != null && header.startsWith(TOKEN_PREFIX)) {
var token = header.replace(TOKEN_PREFIX, "");
var jwtAuthenticationAttempt = new JwtAuthentication(token);
var jwtAuthenticationResult = this.authenticationManager.authenticate(jwtAuthenticationAttempt);
SecurityContextHolder.getContext().setAuthentication(jwtAuthenticationResult);
}
} catch (Exception ex) {
// Build Error Response by a global ResponseEntityExceptionHandler
// Break Filter chain
// Send error back to client
}
chain.doFilter(req, res);
}
}
Он просто оборачивает попробуйте перехватить критические операции.
Моя вторая идея:
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
try {
filterChain.doFilter(request, response);
} catch (Exception ex) {
// Build Error Response by a global ResponseEntityExceptionHandler
// Break Filter chain
// Send error back to client
}
}
Здесь я регистрирую фильтр как можно раньше в цепочке фильтров и объединяю блок try catch вокруг операции фильтра. .
У обеих возможностей есть недостаток, заключающийся в том, что мне приходится проводить различие в двух случаях. Сначала в готовом handleException методе ResponseEntityExceptionHandler и во втором разе в моих решениях, показанных выше, которые вызывают специфический c метод обработчика ResponseEntityExceptionHandler для создания объекта ResponseEntity .
public abstract class ResponseEntityExceptionHandler {
...
@Nullable
public final ResponseEntity<Object> handleException(Exception ex, WebRequest request) throws Exception {
HttpHeaders headers = new HttpHeaders();
if (ex instanceof HttpRequestMethodNotSupportedException) {
HttpStatus status = HttpStatus.METHOD_NOT_ALLOWED;
return handleHttpRequestMethodNotSupported((HttpRequestMethodNotSupportedException) ex, headers, status, request);
}
else if (ex instanceof HttpMediaTypeNotSupportedException) {
HttpStatus status = HttpStatus.UNSUPPORTED_MEDIA_TYPE;
return handleHttpMediaTypeNotSupported((HttpMediaTypeNotSupportedException) ex, headers, status, request);
}
...
else {
// Unknown exception, typically a wrapper with a common MVC exception as cause
// (since @ExceptionHandler type declarations also match first-level causes):
// We only deal with top-level MVC exceptions here, so let's rethrow the given
// exception for further processing through the HandlerExceptionResolver chain.
throw ex;
}
}
}
Было бы идеально, если бы я мог вызвать метод handleException непосредственно из фильтра. Что мешает мне, так это то, что этот метод выдает пропущенное исключение, если обработчик не найден и поскольку метод объявлен как финальный, я не могу реализовать пользовательское решение.
Есть ли подходящее решение для глобальной ошибки обработчик?
Заранее спасибо