Spring Security + JWT 스터디를 하다가 시작된 의문으로 파보게 된 Filter...
첫번째는 Security와는 약간 다른 얘기지만 Servlet Filter의 등록과 동작순서부터 알아봤다.
간단하게 Filter interface를 구현하여 Custom filter를 세개 만들었다.
아래와같이 ATestFilter, BTestFilter, DTestFilter를 만들고 @Component 어노테이션으로 간단하게 등록했다.
@Component
public class ATestFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("----------------------------ATEST Request------------------------------------");
chain.doFilter(request, response);
System.out.println("----------------------------ATEST Response------------------------------------");
}
}
그리고 요청을 보내면
...
----------------------------ATEST Request------------------------------------
----------------------------BTEST Request------------------------------------
----------------------------DTEST Request------------------------------------
...(동작)
----------------------------DTEST Response------------------------------------
----------------------------BTEST Response------------------------------------
----------------------------ATEST Response------------------------------------
순서를 정해주지 않으면 Default로 등록된 컴포넌트의 알파벳 순서에 따라 작동한다.
이 상태에서 순서를 지정하려면 @Order 어노테이션을 이용을 이용해 컴포넌트의 로드 순서를 정한다.
A, B, D Filter의 순서를 거꾸로 3, 2, 1로 지정해줬다.
@Component
@Order(3)
public class ATestFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("----------------------------ATEST Request------------------------------------");
chain.doFilter(request, response);
System.out.println("----------------------------ATEST Response------------------------------------");
}
}
다시 요청을 보내면 순서를 지정한대로 표출된다.
...
----------------------------DTEST Request------------------------------------
----------------------------BTEST Request------------------------------------
----------------------------ATEST Request------------------------------------
...(동작)
----------------------------ATEST Response------------------------------------
----------------------------BTEST Response------------------------------------
----------------------------DTEST Response------------------------------------
이 외에 특정 URL 패턴에만 특정 Filter를 적용하고 싶다면 @WebFilter(urlPatterns= "/user/*") 와 같이 @WebFilter 어노테이션을 이용하는 방법이 있다.
다만 주의해야할 점은 @WebFilter 어노테이션이 붙은 필터를 컴포넌트로 등록하고 싶다면 @ServletComponentScan 어노테이션을 메인 어플리케이션 클래스에 붙여줘야 하며, 만약 Filter 클래스에 @WebFilter와 @Component 어노테이션 두개가 동시에 붙어있다면 @ServletComponentScan, @ComponentScan이 각각 동작할 때 해당 Filter를 두번 등록하여 실행도 두번 될 수 있으니 @WebFilter 사용시 @Component는 지워줘야한다.
Filter 클래스의 직접 수정이 불가능한 경우 @Configuration 을 사용하는 클래스를 만들어 FilterRegistrationBean을 등록하면서 Filter를 FilterRegistrationBean에 추가하면서 URL 패턴이나 order를 지정해줄 수 있다.
그러면 Spring Security를 사용하는 프로젝트에서 위와 같은 Servlet 필터와 Spring Security Filter의 동작 순서는 어떻게 될까?
현재 내 프로젝트의 Security Ffilter chain은 아래와 같다. 그리고 Servlet 필터는 위에 등록한 A, B, C TestFilter가 있다.
JwtAuthenticationFilter에만 로그를 찍어봤다.
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CorsFilter
LogoutFilter
JwtAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
출력된 로그 는 아래와 같다. Spring Security Filter chain이 먼저 동작한 후 Servlet Filter가 동작했다.
-----------------------JwtAuthenticationFilter Request-----------------------
----------------------------DTEST Request------------------------------------
----------------------------BTEST Request------------------------------------
----------------------------ATEST Request------------------------------------
...(동작)
----------------------------ATEST Response------------------------------------
----------------------------BTEST Response------------------------------------
----------------------------DTEST Response------------------------------------
-----------------------JwtAuthenticationFilter Response-----------------------
만약 Custom filter가 Spring Security Filter 보다 먼저 동작하게 하려면 application.yml에 다음과 같이 추가할 수 있다.
spring.security.filter.order=10
이렇게 하면 Spring Security Filter 앞에 10개의 Filter를 넣을 수 있는 공간이 생긴 셈이다.
다음 포스트에서는 이제 본격적으로 Spring Security filter chain을 파헤쳐봐야겠다.
'Java > Spring' 카테고리의 다른 글
[Spring batch] Listener 종류와 작동 순서, Step 작동 순서 (0) | 2022.08.13 |
---|---|
[JPA/QueryDsl] 페이징에서의 N+1 해결 기록 (0) | 2022.05.16 |
[Mybatis] Select시 NullPointerException ... org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible... (0) | 2021.01.18 |
[Spring]WebClient 파라미터 인코딩 (1) | 2021.01.15 |
[Spring][Transaction] 트랜잭션 제외하기, 트랜잭션 제외 안 될 때 (0) | 2020.09.07 |