말 그대로 요청이 실행되기 전에 가로채서 로직을 수행하는 역할을 한다. 스프링에서는 컨트롤러에 있는 요청을 실행하기 전, 컨트롤러의 로직을 실행한 이후에 특정 로직을 수행할 때 사용한다. 인터셉터를 활용하여 모든 컨트롤러 API 내의 중복적인 코드를 줄일 수 있다. 컨트롤러에서 사용되는 공통 로직을 먼저(혹은 나중에) 수행하므로 주로 사용자 인증 정보 확인 을 할 경우에 사용한다.
인터셉터 객체를 생성할 경우 HandlerInterceptorAdapter
를 상속받아야 한다. HandlerInterceptorAdapter 에서 제공하는 메서드는 다음과 같이 세 가지가 있다.
public class Intercepter extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// TODO Auto-generated method stub
return super.preHandle(request, response, handler);
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
// TODO Auto-generated method stub
super.postHandle(request, response, handler, modelAndView);
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
// TODO Auto-generated method stub
super.afterCompletion(request, response, handler, ex);
}
}
preHandle
: 컨트롤러가 호출되기 전에 수행된다.postHandle
: 컨트롤러가 호출된 이후 수행된다.afterCompletion
: 컨트롤러의 처리가 끝나고 화면 처리까지 모두 완료되면 수행된다.예를 들어, 사용자 인증 정보를 토큰으로 관리한다 할 때 토큰이 유효한지 확인하는 과정에서 활용할 수 있다. 다음 예제는 우아한테크코스 장바구니 미션 중 로그인 인터셉터 객체를 가져온 것이다. 컨트롤러 로직이 수행되기 전, 사용자를 식별해야 하는 로직을 요청할 경우(클라이언트로부터 토큰을 받아온다면) 받아온 토큰이 유효한지 확인하는 역할을 한다.
src/main/java/woowacourse/auth/ui/LoginInterceptor.java
package woowacourse.auth.ui;
import org.springframework.web.cors.CorsUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
import woowacourse.auth.application.AuthService;
import woowacourse.auth.support.AuthorizationExtractor;
import woowacourse.shoppingcart.exception.token.InvalidTokenException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class LoginInterceptor extends HandlerInterceptorAdapter {
private final AuthService authService;
public LoginInterceptor(final AuthService authService) {
this.authService = authService;
}
@Override
public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response, final Object handler) throws Exception {
if (CorsUtils.isPreFlightRequest(request)) {
return true;
}
String accessToken = AuthorizationExtractor.extract(request); // 토큰 추출
validateToken(accessToken); // 토큰 확인
return true; // 유효한 토큰일 경우 true 반환하여 컨트롤러 수행
}
private void validateToken(final String accessToken) {
if (accessToken == null || !authService.validateToken(accessToken)) {
throw new InvalidTokenException("로그인을 해주세요.");
}
}
}
인증이 필요한 모든 로직 전에 토큰 정보를 확인해야 하므로 preHandle
메서드를 오버라이딩하였다. 요청 객체로부터 token 을 추출하고 추출한 토큰이 유효한지 확인한다. 유효하지 않을 경우 예외가 발생되며, 유효할 경우 true
를 반환하여 컨트롤러 로직이 수행되도록 한다.
src/main/java/woowacourse/auth/config/AuthenticationPrincipalConfig.java
package woowacourse.auth.config;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import woowacourse.auth.ui.AuthenticationPrincipalArgumentResolver;
import woowacourse.auth.application.AuthService;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import woowacourse.auth.ui.LoginInterceptor;
import java.util.List;
@Configuration
public class AuthenticationPrincipalConfig implements WebMvcConfigurer {
private final AuthService authService;
public AuthenticationPrincipalConfig(AuthService authService) {
this.authService = authService;
}
// 인터셉터 추가
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginInterceptor(authService))
.addPathPatterns("/auth/**"); // 해당 URL 로 들어오는 요청은 LoginInterceptor 실행
}
@Override
public void addArgumentResolvers(List argumentResolvers) {
argumentResolvers.add(createAuthenticationPrincipalArgumentResolver());
}
@Bean
public AuthenticationPrincipalArgumentResolver createAuthenticationPrincipalArgumentResolver() {
return new AuthenticationPrincipalArgumentResolver(authService);
}
}
WebMvcConfigurer
를 구현한 config 객체를 생성하여 Interceptor 를 등록한다. WebMvcConfigurer 는 Spring MVC 에서 필요한 설정들을 관리하는 인터페이스이다. addInterceptors
를 이용하여 앞에서 생성한 LoginInterceptor 를 등록한다. 특정 URL 로 요청이 들어왔을 경우에만 인터셉터를 실행하기 위해 URL 도 설정한다. (사용자를 식별하지 않아도 요청할 수 있는 기능도 있음) excludePathPatterns
를 사용하면 특정 URL 을 제외할 수도 있다.