Spring에서 Request  2번 읽기 - HttpServletRequestWrapper

HttpServlceRequestWrapper

필자가 Restful을 스프링으로 만들고 있을 때 JWT(토큰 인증 방식) 을 이용한 인증방식을 이용하려고 했다. 그 인증을 해주는 Interceptor을 하나 만들어서 토큰을 인증했다. 하지만 interceptor에서 request를 읽어버리면 Controller에서 request를 읽지 못하는 단점이 있다. Controller에서 request를 읽어주게 하는 방법이 바로 HTTPServletRequestWrapper 이다.

최근에 평범한 흐름에서 HttpServletRequest body를 두번 읽고 필터 체인에게 넘겨주는 요구가 많아졌다. ( 필자가 위에서 설명한 방법도 body를 두번 읽어야 한다. 한번은 인증을 위해 읽어야하고 한번은 인증이 되면 그 값들을 이용하려는 컨트롤러에게 줘야 하므로)

HttpServletRequestWrapper 예제

이 커스텀 소스는 HttpServletRequestWrapper 를 구현한 것이다. 자세한 내용은 서블릿 2.5의 내용을 읽어보면 된다.

RequestWrapper.java

HttpServletRequestWrapper 사용하기

이 wrapper를 사용하려면 서블릿 필터를 먼저 추가해줘야 한다. 이 서블릿은 request body를 두번 읽는걸 도와준다. wrapper를 사용하기 위해서 web.xml에 서블릿 필터 매핑을 추가해주자. (위에 소스하고는 무관)

web.xml

/* 이 있기 때문에 위에 있는 필터는 모든 요청들을 필터링 해준다.

서블릿 필터에서 request body를 두번 읽는 법

CacheFilter.java

이 서블릿 필터는 http request body를 원하는 만큼을 읽을 수 있고 filter chain으로 전달도 가능 하다.

마치며

여러분도 알듯이, 기본적으로 http request body 는 오직 한번만 읽을 수 있다. 만약 filter에서 body를 읽었다면, servlet은 다시 읽을 수 없으며 IllegalStateException 오류를 낼 것이다.

위에 있는 HttpServletRequestWrapper 을 사용하면 서블릿에서도 읽을 수 있으며 그 다음에도 읽을 수 있게 된다. 마지막으로 중요한 것은 request body의 컨텐트는 wrapper 오브젝트 안에 캐시화 되어 있어서, request 라이플 사이클 만큼 있을 수 있다.

댓글

이 블로그의 인기 게시물

Filter url 제외시키기

[Spring,Java] Validator 구현하기

[Spring] Mock framework에 대하여