본 블로그의 모든 Spring Security 포스팅은 Spring Boot 3 이상 버전을 기준으로 작성됩니다
DelegatingFilterProxy
Spring Security는 Servlet Filter 레벨에서 인증 및 인가를 처리하기 위한 프레임워크이다
여기서 Servlet Filter 레벨이라는 부분에 포커스를 맞추면 스프링 빈은 Spring IoC Container에서 관리되는 컴포넌트이고 Servlet Level과는 분리된 개념이기 때문에 Servlet Filter에서는 스프링 빈을 주입받아서 활용할 수 없다
- 하지만 결론부터 말하자면 Spring Security에서 활용되는 여러 컴포넌트들은 스프링 빈으로 등록해서 관리되고 여러 빈들을 주입받아서 상호작용해서 동작하게 된다
그렇다면 Servlet Container ↔ Spring IoC Container 사이에서 Bridge역할을 해주는 누군가가 존재한다는 의미이다
그것이 바로 DelegatingFilterProxy이다
DelegatingFilterProxy는 Servlet Level에서 구현된 여러 필터중에 하나일뿐이다
SecurityFilterAutoConfiguration (with DelegatingFilterProxyRegistrationBean)
SecurityFilterAutoConfiguration에서는 DelegatingFilterProxyRegistrationBean이란 클래스를 빈으로 등록하는 모습을 볼 수 있다
- 그런데 @ConditionalOnBean부분을 보니 DEFAULT_FILTER_NAME이라는 이름을 가진 빈이 존재해야 DelegatingFilterProxyRegistrationBean도 등록됨을 알 수 있다
- 확인해보니 springSecurityFilterChain이라는 이름을 가진 빈이 있어야 함을 추정할 수 있다
- DelegatingFilterProxyRegistrationBean을 생성할 때 targetBeanName에는 springSecurityFilterChain이라는 이름이 들어감을 확인할 수 있다
- DelegatingFilterProxyRegistrationBean에서는 getFilter를 통해서 DelegatingFilterProxy를 얻을 수 있고 ServletContainerInitializerBeans의 add 로직에서 이를 활용해서 DelegatingFilterProxy를 add함을 확인할 수 있다
1. SecurityFilterAutoConfiguration을 통해서 DelegatingFilterProxyRegistrationBean을 빈으로 등록 (springSecurityFilterChain이라는 이름을 가진 빈이 존재하는 경우)
2. DelegatingFilterProxyRegistrationBean에서는 getFilter를 통해서 DelegatingFilterProxy 생성
3. ServletContainerInitializerBeans에서 여러 필터들을 add (DelegatingFilterProxy도 포함)
그렇다면 과연 springSecurityFilterChain이라는 이름을 가진 빈은 무엇일까?
FilterChainProxy
바로 FilterChainProxy라는 클래스가 springSecurityFilterChain이라는 이름으로 빈 등록이 되는 것이다
DefaultSecurityFilterChain
그렇다면 FilterChainProxy에 기본적으로 적용되는 Chain인 DefaultSecurityFilterChain은 어떻게 등록되었는지 살펴보자
HttpSecurityConfiguration & SpringBootWebSecurityConfiguration
기본적으로 Spring Security Framework는 개발자가 어떠한 설정도 하지 않은 상태라도 기본적인 인증/인가 처리를 위해서 여러가지 Security Filter들을 Application 로딩 시점에 적용해놓는다
- 위의 코드는 Spring Security 설정에 필수적인 HttpSecurity 클래스를 스프링 빈으로 등록함으로써 커스텀하게 가져다가 여러 설정들을 추가할 수 있게 된다
SpringBootWebSecurityConfiguration 내부에서 가장 Basic한 Security 인증/인가 처리를 위한 SecurityFilterChain을 빈으로 등록함을 확인할 수 있다
이러한 내부 자동 설정으로 인해 우리는 어떠한 설정도 하지 않아도 Security Dependency 추가만으로 여러 인증/인가 처리를 받을 수 있었던 것이다
- 결과로 DefaultSecurityFilterChain이 빈으로 등록되고 기본적인 15개의 필터가 적용됨을 확인할 수 있다
DelegatingFilterProxy → FilterChainProxy 요청 위임 및 처리
지금까지 DelegatingFilterProxy & FilterChainProxy의 기본적인 등록 원리에 대해서 알아보았다
이제 특정 요청에 대해서 다음 2가지 처리 흐름을 살펴보자
- DelegatingFilterProxy가 어떻게 FilterChainProxy로 요청을 위임하고
- FilterChainProxy에서는 위임받은 요청에 대해서 어떻게 처리를 하는지
요청 → http://localhost:8080
SecurityFilterChain → SpringBootWebSecurityConfiguration에 의해서 자동 등록된 SecurityFilterChain
1. DelegatingFilterProxy → FilterChainProxy 요청 위임
DelegatingFilterProxy의 doFilter에서는 현재 들어온 요청을 위임할 delegateToUse를 찾는다
initDelegate 흐름에서는 springSecurityFilterChain이라는 이름으로 등록된 빈을 찾게 된다
- 여기서 바로 FilterChainProxy(DefaultSecurityFilterChain)을 가져오는 것이다
DelegatingFilterProxy에서는 요청을 위임할 delegateToUse(FilterChainProxy)를 찾아왔고 이제 invoke를 통해서 FilterChainProxy로 위임하는 로직으로 들어가게 된다
2. FilterChainProxy에서의 처리
FilterChainProxy에서는 현재 요청을 처리할 Filter들을 가져오는 로직이 보인다
FilterChainProxy가 가지고 있는 List<SecurityFilterChain>에 대해서 loop를 돌면서 matches를 통해 현재 요청에 적절한 chain을 찾은 후 해당 chain이 가지고 있는 필터들을 반환한다
public interface SecurityFilterChain {
boolean matches(HttpServletRequest request);
List<Filter> getFilters();
}
위에서 현재 요청에 대한 필터링을 진행할 chain의 필터를 가져온 후 FilterChainProxy의 static final class인 VirtualFilterChain에서 가져온 필터들에 대해서 순차적으로 필터링을 진행하게 된다