[Spring Security] FilterChain에 대해
이 글은 공부를 하면서 알게 된 내용들을 기록하는 글 입니다. 오류나 고쳐야 할 사항들이 있다면 지적 부탁드립니다!
✅ Filter Chain이란 무엇인가?
Filter chain에 대해 알아보기 전에 `Filter`에 대해 먼저 알아보자. `Filter`란 무엇인가?
기본적으로 `Filter`는 `Servlet`에서의 필터를 이야기하며, Request & Response를 처리할 때마다 실행되는 Java class이다.
Request가 Client로부터 Spring Controller에 도달하기 전에 한 번
Response가 Spring Controller로부터 Client에게 전달되기 전에 한 번 실행되며, 커스텀이 가능하다.
Authentication(인증), Authorization(인가) 뿐만 아니라, Logging과 같은 기능을 넣기도 한다.
밑의 다이어그램은 Servlet Filter Chain의 도식화한 것이다.
Client가 API 요청을 하면
`Web server(Java에서는 Tomcat)` → `Servlet(Java에서는 Dispatcher Servlet)` → `Controller` 순서로 요청이 전달되는데,
그 중 `Filter chain`은 `Web server`와 `Servlet` 사이에서 작동한다.
`ApplicationFilterConfig`의 `internalDoFilter()`에 break point를 잡고 Filter를 확인해볼 수 있다.
Spring에서 제공되는 characterEncodingFilter, Tomcat에서 제공하는 Tomcat WebSocket Filter 등을 확인할 수 있다.
💡 NOTE!
`Tomcat WebSocket Filter`는 HTTP connection을 이 필터에서 처리하기 때문에 항상 제일 마지막에 위치한다.
✅ Spring security's Filter chain
🔥 Spring security에서의 Filter chain은 무엇인가?
🧐 그렇다면 Spring Security에서 코드를 작성하며 보았던 `Filter chain`은 무엇인가?
Spring Security에서는 `Filter` 인터페이스를 구현하여 보안에 필요한 작업들을 수행하는 필터들을 제공한다.
우리가 개발하며 많이 보았던 `UsernamePasswordAuthenticationFilter` 등이 여기에 속한다.
제공하는 필터 뿐만 아니라, 개발하고자하는 서비스의 목적에 맞춰 커스텀 필터를 만들어 적용할 수 있다.
그럼 또 한 가지 의문점이 생긴다.
🧐 Servlet filter에서 Spring security의 filter chain으로 어떻게 넘어가는가?
그 역할을 하는 것이 바로 `DelegatingFilterProxy`와 `FilterChainProxy`이다.
🔥 Security Filter chain의 생성
위에서 개발자가 직접 `커스텀 Filter`를 만들어 적용할 수 있다고 이야기 했는데, 이 `커스텀 Filter`는 어떤 식으로 적용될까?
`SecurityConfig` 클래스(다른 이름도 상관없습니다!)를 만들고, `filterChain()` 메서드를 통해 filterChain에 대한 전반적인 관리가 가능하다.
매개변수의 `HttpSecurity`가 해당 메서드에서 정의한 설정을 기반으로 Filter chain을 생성하며, Application context 초기화 시 진행된다.
@Configuration
@Order(1)
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
...
}
}
🔥 DelegatingFilterProxy
해당 클래스는 IOC Container(Spring Container)에서 관리하는 빈이 아닌 표준 Servlet Filter를 구현하고 있으며, Servlet container와 IOC Container(Spring Container)를 연결하는 역할을 한다.
Client의 Request(요청)을 받아 Servlet Filter Chain을 진행하던 중(Servlet에 넘어가기 전), `DelegatingFilterProxy` 객체에 다다르면 Spring Security의 Filter chain쪽으로 흐름이 넘어간다.
1) `DelegatingFilterProxy`가 Servlet filter chain을 통해 온 요청(Request)를 받는다.
2) Application context에서 SpringSecurityFilterChain 이름으로 생성된 Bean을 찾는다. (이 Bean이 바로 `FilterChainProxy`이다.)
3) Bean을 찾으면 SpringSecurityFilterChain으로 요청을 위임한다.
4) 각각의 Filter들에게 순서대로 요청을 chain 형식으로 넘기며 처리한다.
🔥 FilterChainProxy
`DelegatingFilterProxy`를 통해 요청을 위임받아 실제로 작업을 처리하는 부분이다.
Spring security의 Filter Chain의 진입점으로 `SecurityContextPersistenceFilter`부터 시작해 다양한 필터들을 거치게 된다.
필터를 순차적으로 실행하며 마지막 필터까지 Exception이 발생하지 않으면, 요청을 DispatcherServlet 쪽으로 넘긴다.
Filter chain을 하나만 설정하는 것이 아니라 여러 개 설정할 수도 있는데, `FilterChainProxy`가 요청에 따라 어떤 Filter chain을 사용할지도 결정한다.
✅ Filter들 간의 작동 방식 (업데이트 예정)
`FilterChainProxy`는 Spring security의 Filter chain를 통해 요청이 다양한 Filter들을 거쳐갈 수 있도록 한다.
이 Filter chain에는 다양한 필터들이 있는데, `FilterChainProxy`의 생성자에 break point를 찍고 디버그 모드로 돌리면 기본으로 설정된 필터들을 확인해볼 수 있다.
✅ 참고 자료 & 링크
- https://www.youtube.com/playlist?list=PLrHjhj3I5M_ljv8s-Bejj4tbYPjOnjwQp
- https://velog.io/@yaho1024/spring-security-delegatingFilterProxy
- https://atin.tistory.com/590