Обработка исключений в Spring GenericFilterBean

Я реализовал аутентификацию на основе токенов (без защиты spring). Таким образом, в GenericFilterBean он проверяет и утверждает токен.

public class MyTokenFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws MyAuthException {

        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (!"OPTIONS".equals(request.getMethod())) {

            String authHeader = request.getHeader("Authorization");

            if (authHeader == null || !authHeader.startsWith("Token ")) {
                throw new MyAuthException("Authorization header needed"); // Should return custom http status response like 400
            }

            String token = authHeader.substring(6);

            try {
                claimToken(token);
            } catch (Exception e) {
                throw new MyAuthException("Invalid token."); // Should return custom http status response like 401
            }

        }

        chain.doFilter(req, res);

    }

}

Итак, в этом фильме все выглядит нормально. Но мне нужно отправить ответ с разными уставами Http с помощью json. Я могу использовать ResponseEntitiyExceptionHandler с @ControllerAdvice. Поэтому я могу обрабатывать исключения в моих контроллерах.

@ControllerAdvice
public class MyPrettyExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(MyAuthException.class)
    @ResponseBody
    public ResponseEntity<Object> handleCustomException(HttpServletRequest req, MyAuthException ex) {
        Map<String, String> responseBody = new HashMap<>();
        responseBody.put("error", "true");
        responseBody.put("message", ex.getMessage());
        return new ResponseEntity<Object>(responseBody, HttpStatus.INTERNAL_SERVER_ERROR);
    }
}

Я знаю, как это работает, и какой порядок фильтров и контроллеров и их исключения (фильтры выполняют свою работу перед контроллерами, поэтому они не одинаковы с контроллерами). Поэтому, естественно, я не могу обрабатывать исключения фильтров с помощью ControllerAdvice.

Итак, каков эффективный способ обработки исключений в фильтрах (например, мой пример)? Можете ли вы предложить мне другой способ?

Ответ 1

Вы должны использовать response.sendError для кода и статуса ошибки отправки:

public class MyTokenFilter extends GenericFilterBean {

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest) req;
        HttpServletResponse response = (HttpServletResponse) res;

        if (!"OPTIONS".equals(request.getMethod())) {

            String authHeader = request.getHeader("Authorization");
            if (authHeader == null || !authHeader.startsWith("Token ")) {
                //throw new MyAuthException("Authorization header needed"); // Should return custom http status response like 400
                response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Authorization header needed");
                return ;
            }

            String token = authHeader.substring(6);
            try {
                claimToken(token);
            } catch (Exception e) {
                //throw new MyAuthException("Invalid token."); // Should return custom http status response like 401
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Invalid token.");
                return ;
            }
        }
        chain.doFilter(req, res);
    }
}