Spring Security - Filters ( DelegatingFilterProxy, FilterChainProxy )

이번 글에서는 Spring Security Filter Chain 에 대해서 정리를 하려고 한다.



Spring Security web infrastructure 는 Servlet 

filter 기반이다.  

아래의 이미지를 보면, http request 가 어떻게 처리 될 지 명백하게 이해할 수 있을것이다. 

Client 는 Application 으로 요청을 보낸다. 그리고 해당 요청은 어떤 filter 들과 어떤 servlet 이 적용되야 하는지 request URI 에 따라서 판별된다. 최대 하나의 servlet 은 하나의 request 만 처리할 수 있지만, filter 는 chain 을 이루고 순서가 지정되며 실제로 request 자체를 처리할 때 filter 가 나머지 chain 이 처리 되지 않도록 할 수 있다. filter 는 이후에 적용될 filter 및 servlet 에 사용 될 request 와 response 를 수정할 수도 있다. 따라서 filter chain 의 순서는 매우 중요하다.

Spring Boot 에서는 두 가지 메커니즘을 통해 filter chain 을 관리한다.
  1. Filter Type 의 @Beans 은 @Order 를 가지거나 Ordered 를 구현한다.
    one is that @Beans of type Filter can have an @Order or implement Ordered
  2. Filter 들이 API 의 일부로서 순서를 갖는 FilterRegistrationBean 의 일부가 될 수 있다.
    the other is that they can be part of a FilterRegistrationBean that itself has an order as part of its API.
기존의 Spring Security 에서 존재하는 Filters 들은 서로 간의 순서를 쉽게 알릴 수 있도록 상수를 가진다.
(e.g. the SessionRepositoryFilter from Spring Session has a DEFAULT_ORDER of Integer.MIN_VALUE + 50, which tells us it likes to be early in the chain, but it doesn’t rule out other filters coming before it).

Spring Security 는 하나의 Filter 만 사용한다. 해당 Filter Type 은 FilterChainProxy 이다. 


Spring Boot Application 에서 Security Filter 는 ApplicationContext 의 @Bean 이며 모든 요청에 기본적으로 적용된다.
SecurityProperties.DEFAULT_FILTER_ORDER 에 의해 정의 된 위치에 설치되며, FilterRegistrationBean.REQUEST_WRAPPER_FILTER_MAX_ORDER 에 의해 고정된다.
컨테이너 보안의 관점에서 보면 Spring Security Filter 는 Single Filter 이지만, 내부에는 각각 특별한 역할을 하는 추가 Filter 가 있다.

실제로 Spring Security Filter 에는 간접 계층이 하나 더 있다. 일반적으로 컨테이너에 DelegatingFilterProxy 로 설치 된다. DelegatingFilterProxy 는 항상 @Bean 인 FilterChainProxy 에 위임한다. 보통 @Bean name 은 springSecurityFilterChain 이다. FilterChainProxy 는 내부적으로 Filter Chain 으로 내부에 배열 된 모든 보안 로직을 포함한다. 모든 필터는 동일한 API 를 가지며 (모두 Servlet Spec 을 따르는 Filter Interface 를 구현 함) 나머지 chain 을 거부 할 수 있다.


Spring Security 는 여러 개의 Filter Chain 을 가질 수 있다.

동일한 최상위 레벨 FilterChainProxy 에서 Spring Security 의해 관리되는 여러 개의 Filter Chain 이 있을 수 있다. 아래의 이미지를 보자. uri path 에 따라 filter chain 을 dispatch 하고 있다.

커스텀 security configuration 이 아닌 vanilla security configuration 에서는 보통 6개의 filter chain 을 구비하고 있다.
  • static resource patterns 을 무시하는 chain 이다. ( /css/** , /images/** )
  • 그리고 error view 나타내는 /error path ( path 는 security.ignored from the SecurityProperties configuration bean 으로 조절이 가능하다.)
  • /** 와 같이 모든 path 를 아우르며 인증, 권한 부여, 예외 처리, 세션 처리, 헤더 작성 등을 위한 논리를 포함한다. 기본적으로 해당 chain 에는 총 11개 의 filter 가 있지만 일반적으로 어떤 filter 가 언제 사용되는지 사용자는 걱정할 필요가 없다.

아래에는 필자가 직접 디버깅을 해보았다.

아래의 이미지는 DelegatingFilterProxy 의 doFilter() 메서드이다.
this.delegate 에 FilterChainProxy 을 대입하고 invokeDelegate() 메서드를 통해서 FilterChainProxy 에게 위임하고 있다.

아래 debug stack trace 을 통해 확인할 수 있다. ApplicationFilterChain 의 5번 째 Filter 에 DelegatingFilterProxy 가 지정되어 있음을 알 수 있다. DelegatingFilterProxy 는 FilterChainProxy 에게 위임한다. 

아래의 사진은 FilterChainProxy 의 doFilter 메서드 이다.

FilterChainProxy 는 아래의 이미지와 같이 총 9개의 Filter 를 가지고 있다. 
FilterChainProxy request 의 path 에 맞게 설정된 filter chain (현재는 9개의 filter) 로 dispatch 하고, 해당 filter 들의 doFilter() 메서드를 호출한다.

이번 글에서는 Spring Security 의 Filter 메커니즘에 대해서 정리해보았다.

댓글

이 블로그의 인기 게시물

About JVM Warm up

About idempotent

About Kafka Basic

About ZGC

sneak peek jitpack

Spring Boot Actuator readiness, liveness probes on k8s

About Websocket minimize data size and data transfer cost on cloud

About G1 GC

대학생 코딩 과제 대행 java, python, oracle 네 번째