(스프링) 인터셉터 사용하기

로그인 하지 않은 상태에서 비밀번호를 바꾸는 URL주소를 입력하면, 비밀번호 변경 폼이 출력될 것이다.
로그인하지 않았는데 변경 폼이 출력되는 것은 다소 이상하다.
그것보다는 로그인하지 않은 상태에서 비밀번호 변경 폼을 요청하면, 로그인 화면으로 이동시키는 것이 더 좋은 방법인 것 같다.



이를위해, HttpSession에 "authInfo"객체가 존재하는지 검사해서, 존재하지 않으면 로그인 경로로 리다이렉트하도록 구현한 코드를 컨트롤러 클래스에 추가한 것이다.


그런데 실제 웹 어플리케이션에서는 비밀번호 변경 기능외에 더 많은 기능이 로그인 여부를 확읺야 하는데, 각 기능을 구현한 컨트롤러 코드에 위와 같이 세션을 확인하는 코드를 삽입하는 것은 많은 중복을 발생시킨다.

이렇게 다수의 컨트롤러에 대해 동일한 기능을 적용해야 할 때 사용할 수 있는 것이 인터셉터이다. 스프링은 인터셉터를 지원하기 위해 HandlerInterceptor인터페이스를 제공한다.



1. HandlerInterceptor 인터페이스 사용하기


다음의 세 가지 시점에 공통기능을 넣을 수 있다.
  • 컨트롤러(핸들러)실행 전
  • 컨트롤러(핸들러)실행 후, 아직 뷰를 실행하기 전
  • 뷰를 실행한 이후
다음의 세 개의 메소드를 정의하고 있다.
  • boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)throws Exception;
  • void postHandle(HttpServletRequest request, HttpServletResponse response,Object handler, ModelAndView modelAndView)throws Exception;
  • void afterCompletion(HttpServletRequest request, HttpServletResponse response,Object handler,Exception ex)throws Exception;

preHandle()메소드를 사용하면 로그인하지 않은 경우 컨트롤러를 실행하지 않는다거나, 컨트롤러를 실행하기 전에 컨트롤러에서 필요로 하는 정보를 생성하는 등의 작업이 가능하다. 리턴 타입이 boolean인데, false를 리턴하면 컨트롤러(또는 다음 HandleInterceptor)를 실행하지 않는다.

postHandle()메소드는 컨트롤러가 정상적으로 실행된 이후에 추가 기능을 구현할 때 사용한다. 만약 컨트롤러가 익셉션  발생하면 postHandle()메소드는 실행되지 않는다.


aftercompletion() 는 뷰가 클라이언트에 응답을 전송한 뒤에 실행된다. 만약 컨트롤러를 실행하는 과정에서 익셉션이 발생하면, 이 메소드의 네 번째 파라미터로 전달된다. 
익셉션이 발생하지 않았다면 네 번쨰 파라미터는 null이 된다. 
따라서 컨트롤러 실행 이후에 예기치 않게 발생한 익셉션을 로그로 남긴다거나 실행 시간을 기록하는 등의 후처리를 하기에 적합한 메소드이다.



HandlerInterceptorAdapter클래스는 HandleInterceptor인터페이스를 구현하고 있는데 각 메소드는 아무 기능도 수행하지 않는다. 따라서, HandlerInterceptor 인터페이스의 메소드를 모두 구현할 필요가 없다면, HandlerInterceptorAdapter 클래스를 상속받은 뒤 필요한 메소드만 재정의하면 된다.



비밀번호 변경 기능에 접근할 때 HandlerInterceptor를 사용하면 로그인 여부에 따라 로그인 폼으로 보내거나 컨트롤러를 실행하도록 구현할 수 있다. 
여기서 만들 핸들러인셉터 구현 클래스는 preHandle()메소드에서 HttpSession에 "authInfo"속성이 존재하는지 여부에 따라 지정한 경로로 리다이렉트하도록 구현하면 된다.


preHandle() 메소드의 구현을 보면 HttpSession에 "authInfo"가 존재할 경우 true를 리턴하고, 그렇지 않으면 리다이렉트 응답을 생성한 뒤 false를 리턴한다.
true를 리턴하면 컨트롤러를 실행하므로, 로그인 상태면 컨트롤러를 실행한다. 반대로 false를 리턴하면 로그인 상태가 아니므로 다음 경로로 리다이렉트한다.


2. HandlerInterceptor 설정하기

스프링컨트롤러.xml에 다음을 추가한다.


<mvc:mapping>: HandlerInterceptor를 적용할 경로를 지정한다. Ant경로 패턴을 사용할 수 있으며, 위 코드에서는 /edit/로 시작하는 모든 경로에 HandleInterceptor를 적용하도록 설정되있다.

예를들어 @RequestMapping("/edit/changePassword")
가 적용된 비밀번호를 바꾸는 컨트롤러 클래스에 적용된 곳이다.


댓글

이 블로그의 인기 게시물

(ElasticSearch) 결과에서 순서 정렬

(네트워크)폴링방식 vs 롱 폴링방식

(18장) WebSocekt과 STOMP를 사용하여 메시징하기