Spring Security는 여러 필터(Filter)를 체인(Chain) 형태로 구성하여 서블릿(Servlet) 컨테이너에서 동작한다. 개발자는 주로 HttpSecurity를 이용해 SecurityFilterChain 빈을 등록하는 방식으로 보안 설정을 적용하지만, 이 빈이 실제 요청을 처리하는 과정은 내부적으로 여러 단계를 거친다.
Spring Security의 웹 보안 기능은 @EnableWebSecurity 어노테이션을 통해 활성화된다. 이 어노테이션은 내부적으로 @Import를 사용하여 WebSecurityConfiguration과 같은 핵심 설정 클래스들을 불러온다.
WebSecurityConfiguration은 Spring Security의 필터 체인을 관장하는 가장 중요한 빈인 springSecurityFilterChain을 생성하고 등록하는 역할을 수행한다. 여기서 springSecurityFilterChain이라는 이름으로 등록되는 빈이 바로 FilterChainProxy의 구현체이다.
Spring Boot의 자동 설정은 DelegatingFilterProxy라는 서블릿 필터를 서블릿 컨테이너에 등록한다. 이 필터는 Spring Security가 실제 요청을 처리하는 관문 역할을 한다.
DelegatingFilterProxy:
DelegatingFilterProxy는 기본적으로 springSecurityFilterChain이라는 이름의 빈을 찾아 요청을 전달한다.FilterChainProxy:
DelegatingFilterProxy로부터 요청을 위임받는 Spring Security의 핵심 필터이다. FilterChainProxy는 자신 내부에 여러 개의 SecurityFilterChain을 리스트 형태로 관리하며, 들어온 요청에 가장 적합한 하나의 SecurityFilterChain을 선택하여 보안 처리를 진행한다.따라서 모든 웹 요청은 서블릿 컨테이너 → DelegatingFilterProxy → FilterChainProxy 순서로 전달됩니다.
실제 보안 규칙(인증, 인가 등)은 개발자가 직접 설정 클래스에 정의하는 SecurityFilterChain 빈에 담겨 있다.HttpSecurity 빌더를 사용하여 이 빈을 생성한다.
@Configuration
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(authz -> authz
.requestMatchers("/api/public/**").permitAll()
.anyRequest().authenticated()
)
.formLogin(Customizer.withDefaults());
return http.build();
}
}
HttpSecurity: SecurityFilterChain을 생성하기 위한 빌더 객체 authorizeHttpRequests, formLogin, csrf 등 메서드 체이닝을 통해 구체적인 보안 규칙을 설정합니다.SecurityFilterChain: HttpSecurity에 의해 생성된 결과물로 특정 경로에 적용될 필터들의 목록과 규칙을 담고 있는 객체이다.애플리케이션은 여러 개의 SecurityFilterChain 빈을 가질 수 있다. 예를 들어 /api/** 경로에 대한 규칙과 /admin/** 경로에 대한 규칙을 별도의 빈으로 분리하여 정의할 수 있다.
FilterChainProxy는 애플리케이션 컨텍스트에 등록된 모든 SecurityFilterChain 빈들을 수집하여 내부 리스트에 저장한다. 그리고 요청이 들어올 때마다 다음의 과정을 거친다.
FilterChainProxy는 자신이 관리하는 SecurityFilterChain 리스트를 순회한다.SecurityFilterChain이 해당 요청 URL과 매칭되는지 requestMatches() 메서드를 통해 확인한다.SecurityFilterChain 하나를 선택하고, 해당 체인에 속한 필터들(ex: UsernamePasswordAuthenticationFilter, AuthorizationFilter)을 순서대로 실행한다.이러한 구조 덕분에 개발자는 HttpSecurity를 통해 선언적으로 보안 규칙을 정의하기만 하면 FilterChainProxy가 알아서 적절한 규칙을 선택하여 동적으로 필터 체인을 적용할 수 있다.