Spring

[Spring] Interceptor를 사용해 Security를 구현해보자 (Filter vs Interceptor)

Sol b 2023. 12. 29. 12:17

대부분의 애플리케이션은 인증, 인가를 통해 접근을 제어하고 있습니다.

그만큼 인증, 인가는 중요한 부분이라고 생각합니다.

이번에 웹 애플리케이션에서 이뤄지는 인증, 인가를 공부해 볼 겸

Interceptor를 사용해 접근 처리를 간단하게 구현해 보았습니다.

 

인증 인가는 Filter로도 많이 구현할 수 있습니다.

Filter와 Interceptor의 차이는 다른 블로그에서 자세히 설명한게 많으니 링크만 달고 생략하겠습니다.

[Filter, Interceptor, AOP 차이 및 정리] (https://goddaehee.tistory.com/154)

 

Interceptor

보통 인증, 인가는 SecurityFilter를 사용해 구현하곤 했습니다.

하지만 이번에는 Interceptor를 사용해 볼 것입니다.

 

다수의 컨트롤러에 동일한 기능을 제공하기 위해 사용하는 것이 인터셉터입니다.

 

Interceptor 생명주기

  • preHandle() : 컨트롤러 실행 전
  • postHandle() : 컨트롤러 실행 후
  • afterCompletion() : 뷰 실행 후

위 3가지 메서드가 있습니다.

Interceptor를 사용하면 컨트롤러 실행 전에 인증, 인가를 검증할 수 있습니다.

 

구현해보기

처음에는 HandlerInterceptor의 구현체 SecurityInterceptor를 구현하여 시도해 보았습니다.

간단하게 세션의 값을 확인하는 코드입니다.

@Component
public class SecurityInterceptor implements HandlerInterceptor {

    /**
     * Web 요청시마다 Login 검증을 하기 위해 재정의
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    	... 중략
        System.out.println("in preHandle");
        ... 중략
        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
    	... 중략
        System.out.println("in postHandle");
        ... 중략
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
    	... 중략
        System.out.println("in afterCompletion");
        ... 중략
    }
}

 

그런데 Interceptor가 동작하지 않았습니다.

그 이유는 Interceptor에 대한 구성정보를 설정하지 않았기 때문입니다.

 

Interceptor 등록을 위한 WebMvcConfigurer

WebMvcConfigurer를 사용해 Interceptor를 등록, 설정할 수 있습니다.

Interceptor의 동작 범위도 여기에 등록할 수 있습니다.

 

구현한 SecurityInterceptor를 Bean으로 등록하여 WebMvcConfigurer에서 등록하였습니다.

@Configuration
public class SecurityWebMvcConfig implements WebMvcConfigurer {

    private final SecurityInterceptor securityInterceptor;

    public SecurityWebMvcConfig(SecurityInterceptor securityInterceptor) {
        this.securityInterceptor = securityInterceptor;
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(securityInterceptor);
    }
}

 

결과

 

Interceptor를 등록해주니 Interceptor의 3가지 메서드가 잘 작동하는것을 확인하였습니다.

Interceptor의 3가지 메서드를 사용하여 다양한 검증을 할 수 있도록 더 연습해봐야겠습니다.

 

CSS 에러

Interceptor를 적용하고 로그인 페이지는 인증, 인가를 허용하기위해

.excludePathPatterns()에 아래와 같이 등록하였습니다.

... 중략 ...

	public static final String LOGIN_PAGE = "/login";
        
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(securityInterceptor)
                .excludePathPatterns(
                        LOGIN_PAGE
                );
    }

 

그런데 CSS가 적용되지 않아 화면이 깨져서 보였습니다...

 

 

찾아보니 CSS와 JS가 있는 폴더까지 Interceptor가 영향이 있어보였습니다.

아래와 같이 코드 변경 후 해결되었습니다.

... 중략 ...

    public static final String LOGIN_PAGE = "/login";
    public static final String CSS = "/css/**";
    public static final String JS = "/js/**";
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(securityInterceptor)
                .excludePathPatterns(
                        CSS,
                        JS,
                        LOGIN_PAGE
                );
    }