JWT 만료 메시지

JWT 기반으로 Stateful한 서버를 만들고 있다.

Frontend에서는 JWT의 유효기간이 다 된다면 재발급을 받아야 한다. 따라서 서버에서는 Frontend에서 온 JWT를 검사하고, 만료가 되었다면 만료 메시지를 보낼 필요가 있다.


그냥 보내면 안돼?

JWT를 검사할 때, TokenExpiredException으로 메시지를 예외처리 해줄 수 있을 것 같다.

사실 된다면 이런 글을 쓰지 않았을 것이다.

images_hellonayeon_post_4ec2d270-11bd-43c7-ac02-829b0ae9b280_image.png

JWT 를 검사하는 위치는 Dispatcher Servlet 앞단에 위치한다.

그 말은 일반 Spring의 Exception으로는 처리 하지 못한다는 뜻이다.

따라서 JwtAuthorizationFilter 바로 앞에 JwtExceptionFilter를 두어 JwtAuthorizationFilter 로 부터 나온 Exception들을 처리해주면 된다.


JwtExceptionFilter

public class JwtExceptionFilter extends OncePerRequestFilter {

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        try {
            filterChain.doFilter(request, response);
        } catch (TokenExpiredException e){
            setErrorResponse(request, response, e);
        }
    }

    // ex.getMessage() 에는 jwtException을 발생시키면서 입력한 메세지가 들어있다.
    public void setErrorResponse(HttpServletRequest req, HttpServletResponse res, Throwable ex) throws IOException {

        res.setContentType(MediaType.APPLICATION_JSON_VALUE);

        final Map<String, Object> body = new HashMap<>();
        body.put("status", HttpServletResponse.SC_UNAUTHORIZED);
        body.put("error", "Unauthorized");
        body.put("message", ex.getMessage());
        body.put("path", req.getServletPath());

        final ObjectMapper mapper = new ObjectMapper();
        mapper.writeValue(res.getOutputStream(), body);
        res.setStatus(HttpServletResponse.SC_OK);
    }
}

해당 필터는 TokenExpiredException을 처리해주기 위해 만들어졌다.

원하는 메시지의 내용을 Response에 담아 보낸다.