java - restcontroller - Spring GenericFilterBean에서의 예외 처리



spring mvc global error handler (1)

토큰 기반 인증 (스프링 보안없이)을 구현했습니다. 따라서 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);

    }

}

그래서이 필터에서는 괜찮아 보입니다. 하지만 JSON으로 다른 Http Statutes와 응답을 보내야합니다. @ControllerAdvice와 함께 ResponseEntitiyExceptionHandler를 사용할 수 있습니다. 따라서 컨트롤러에서 예외를 처리 할 수 ​​있습니다.

@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로 필터의 예외를 처리 할 수 ​​없습니다.

그렇다면 필자의 예제처럼 필터에서 예외를 처리하는 효율적인 방법은 무엇입니까? 그것에 대해 다른 방법을 제안 해 주시겠습니까?


오류 코드 및 상태를 보내려면 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);
    }
}




spring-boot