'interceptor'에 해당되는 글 1건

[Spring 3.2] Interceptor에서 Controller의 어노테이션 체크하기 2013.12.02

[Spring 3.2] Interceptor에서 Controller의 어노테이션 체크하기

Published on: 2013. 12. 2. 19:45 by louis.dev

인증이 필요한 서비스를 개발할 경우, Interceptor에서 로그인 유무를 확인하는 로직을 추가하여 각 컨트롤러에 인증 로직을 추가로 작성하지 않도록 할수 있습니다.


만약 이때 어떤 컨트롤러의 메소드는 로그인을 체크하고 어떤 컨트롤러의 메소드에는 로그인을 체크하지 않도록 하려면 어떻게 해야 할까요?


스프링 3.2 부터는 mvc:interceptor 부분에 exclude-mapping 이라는 엘리먼트가 추가되어 기존의 스프링 버전보다 쉽게 인터셉터의 적용을 제외시킬수 있습니다.

<mvc:interceptor> <mvc:mapping path="/**"/> <exclude-mapping path="/info/**"/> <bean class="net.krespo.interceptor.LoginCheckInterceptor" /> </mvc:interceptor>

이렇게 exclude-mapping을 사용하면 LoginCheckInterceptor는 /info/ 로 시작하는 컨트롤러에 인터셉터 적용을 제외 시킬수 있습니다.


그런데 만약 /info/my는 로그인 인터셉터를 수행시키고 /info/test는 로그인 인터셉터를 수행시키려면 어떻게 해야할까요?


물론 exclude-mapping을 여러개 등록하면 되지만 로그인이 필요하지 않은 컨트롤러가 생길때마다 exclude-mapping을 선언하는것이 귀찮게 느껴질겁니다.


이럴때는 임의의 어노테이션을 생성하여 인증이 필요하지 않은 컨트롤러의 메소드에 어노테이션을 붙이고, 어노테이션 유무를 인터셉터에서 확인하여 로그인을 할지 안할지를 하면 좀더 편하게 개발을 진행할 수 있을것 같습니다.


이제부터 본격적으로 인터셉터에서 컨트롤러의 어노테이션을 체크하는 방법을 알아보도록 하겠습니다.


1. 어노테이션 생성

package net.krespo.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;


@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NoLoginCheck {
}

NoLoginCheck라는 어노테이션을 생성하였습니다. 이 어노테이션을 사용하여 어노테이션을 메소드에 추가를 했으면 로그인 체크를 하고, 어노테이션이 없으면 로그인 체크를 하지 않도록 할것입니다.


2. 컨트롤러에 어노테이션 추가


@Controller
public class MyController {
	
	@RequestMapping("/my/info")
	@NoLoginCheck 
	public ModelAndView myInfo(){
		...
	}
	
}

3. Interceptor에서 어노테이션 체크하기

public class LoginInterceptor extends WebContentInterceptor {
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws ServletException {
		//@NoCheckLogin 어노테이션이 컨트롤러에 사용되었는지 체크함
		NoCheckLogin usingAuth = ((HandlerMethod) handler).getMethodAnnotation(NoCheckLogin.class);

		//NoCheckLogin 어노테이션이 없음으로 무조건 로그인 체크
		if(usingAuth == null) {
			//TODO 로그인 체크
		}
		//NoCheckLogin 어노테이션이 없음으로 로그인 체크 하지 않음
		else {
			//TODO 추가작업
		}
	}	
}

가장 중요한 부분은 preHandler 메소드의 handler Object를 HandlerMethod로 타입케스팅 하는 부분입니다. 이렇게 HandlerMethod로 바꾼 handler오브젝트의 getMethodAnnotation을 통해서 앞으로 실행될 컨트롤러의 메소드에 해당 어노테이션이 추가가 되었는지 안되어 있는지를 확인할 수 있습니다.


위 내용은 스프링 3.2에서 확인해 보았습니다. 그러나 스프링 3.0에서는 해당 handler Object를 HandlerMethod의 오브젝트가 아닌 앞으로 실행시킬 컨트롤러오브젝트(위의 예제에서는 LoginController)가 반환이 됨으로 위의 코드는 3.0에서는 사용할 수가 없습니다~(3.1에서는 체크를 해보지 못했습니다. 3.1에서 사용해 보신 분께서는 댓글로 알려주세요~^^)