Spring Security 공식 문서 - Architecture
https://docs.spring.io/spring-security/reference/servlet/architecture.html
Architecture :: Spring Security
The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for a number of different purposes, like authentication, authorization, exploit protection, and more. The filters are executed in a spec
docs.spring.io
Servlet Application
Spring Security는 표준 Servlet Filter를 사용하여 Servlet Container와 통합된다.
즉, Servlet Container에서 실행되는 모든 application과 함께 동작한다.
더 구체적으로 말하면, Spring Security의 이점을 활용하기 위해 Servlet-based application에서 Spring을 사용할 필요가 없다.
Filter란?
- HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 코드
- 객체의 형태로 존재
- 클라이언트로부터 오는 요청(Request)과 최종 자원 사이에 위치하여 클라이언트의 요청 정보를 알맞게 변경 가능
- 최종 자원과 클라이언트로 가능 응답(Response) 사이에 위치하여 최종 자원의 요청 결과를 알맞게 변경 가능

- 자원이 받게 되는 요청 정보는 클라이언트와 자원 사이에 존재하는 필터에 의해 변경된 요청 정보가 된다.
- 클라이언트가 보게 되는 응답 정보는 클라이언트와 자원 사이에 존재하는 필터에 의해 변경된 응답 정보가 된다.
- 필터는 클라이언트와 자원 사이에 1개만 존재하는 경우가 보통이지만, 여러 개의 필터가 모여서 하나의 체인(chain)을 형성할 수 있다.
javax.servlet에 존재하는 Filter 인터페이스
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException;
default void destroy() {
}
}
Architecture
A Review of Filters
Spring Security의 Servlet 지원은 Servlet Filter를 기반으로 하기 때문에, Filter의 역할을 먼저 알아두는 것이 좋다.
다음 이미지는 하나의(single) HTTP 요청에 대한 handler의 일반적인 layering을 보여준다.

클라이언트는 application에 요청을 보내고, Container는 요청 URI의 경로를 기반으로 HttpServletRequest를 처리해야 하는 Filter 인스턴스와 Servlet을 포함하는 FilterChain을 생성한다.
Spring MVC application(응용 프로그램)에서 Servlet은 DispatcherServlet의 인스턴스이다.
많아야 하나의 Servlet이 하나의 HttpServletRequest 및 HttpServletResponse를 처리할 수 있다.
하지만, 둘 이상의 Filter를 사용하여 다음 작업을 수행할 수 있다.
- Downstream Filter 인스턴스 또는 Servlet이 호출되지 않도록 한다. (무슨 말인지 모르겠다.) 이 경우 Filter는 일반적으로 HttpServletResponse를 쓴다(write).
- Downstream Filter 인스턴스와 Servlet에서 사용하는 HttpServletRequest 또는 HttpServletResponse를 수정한다.
Filter의 힘은 FilterChain에서 나온다.
FilterChain Usage Example
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
Filter는 downstream Filter 인스턴스와 Servlet에만 영향을 미치기 때문에, 각 Filter가 호출되는 순서가 매우 중요하다.
(downstream이라는게 그 다음 순서를 의미하는 거 같기도 하다.)
DelegatingFilterProxy
: Servelt Filter를 구현한 Spring Bean에게 요청을 위임해주는 대리자 역할의 Servlet Filter

Spring은 Servlet container의 라이프 사이클과 Spring의 ApplicationContext 사이의 연결(bridging)을 허용하는 DelegatingFilterProxy라는 Filter 구현체를 제공한다.
Servlet Container는 자체 표준을 사용하여 Filter 인스턴스를 등록할 수 있지만, Spring이 정의한 Bean을 알지 못한다.
표준 Servlet Container 메커니즘을 통해 DelegatingFilterProxy를 등록할 수 있지만 Filter를 구현하는 Spring Bean에 모든 작업을 위임(delegate)할 수 있다.



다음은 DelegatingFilterProxy가 Filter 인스턴스들과 FilterChain에 어떻게 적용되어 있는지 보여주는 그림이다.

DelegatingFilterProxy는 ApplicationContext에서 Bean Filter0을 찾은 다음 Bean Filter0을 호출한다.
다음은 DelegatingFilterProxy의 pseudo code를 보여준다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
Filter delegate = getFilterBean(someBeanName); // (1)
delegate.doFilter(request, response); // (2)
}
(1) Spring Bean으로 등록된 Filter를 lazy하게 가져온다. 위의 코드에서 delegate는 Bean Filter0의 인스턴스이다.
(2) 작업을 Spring Bean에게 위임한다.
FilterProxy에 대한 모든 호출이 표준 Servlet Filter 인터페이스를 구현하는 데 필요한 Spring context의 해당 bean에 위임된다.
DelegatingFilterProxy의 또 다른 장점은 Filter bean 인스턴스 조회를 지연시킬 수 있다는 점이다.
이는 container가 시작하기 전에 Filter 인스턴스를 등록해야 하기 때문에 중요하다.
그러나, Spring은 일반적으로 ContextLoaderListener를 사용하여 Spring Bean을 등록(load)하는데, 이 작업은 Filter 인스턴스를 등록해야 할 때까지 수행되지 않는다.
FilterChainProxy
Spring Security의 Servlet 지원은 FilterChainProxy 내에 포함되어 있다.
FilterChainProxy는 SecurityFilterChain을 통해 많은 Filter 인스턴스들에게 위임할 수 있는 Spring Security에서 제공하는 특수한 Filter이다.
FilterChainProxy는 Bean이기 때문에 일반적으로 DelegatingFilterProxy로 감싸진다.



다음 이미지는 FilterChainProxy의 역할을 보여준다.

SecurityFilterChain
SecurityFilterChain은 FilterChainProxy에서 현재 요청에 대해 호출할 Spring Security의 Filter 인스턴스를 결정하는 데 사용된다.

다음 이미지는 SecurityFilterChain의 역할을 보여준다.

SecurityFilterChain의 Security Filter들은 일반적으로 Bean이지만, DelegatingFilterProxy가 아닌 FilterChainProxy에 등록되어 있다.
FilterChainProxy는 Servlet Container 또는 DelegatingFilterProxy에 직접 등록하는 데에 많은 이점을 제공한다.
2개의 이점은 너무 어려워서 공식 문서를 참고하자.
또한, SecurityFilterChain을 호출해야 하는 시기를 결정하는 데 더 많은 유연성을 제공한다.
Servlet Container에서 Filter 인스턴스는 URL에만 기반하여 호출되지만, FilterChainProxy는 RequestMatcher 인터페이스를 사용하여 HttpServletRequest에 있는 모든 것에 기반하여 호출을 결정할 수 있다.
다음 이미지는 여러 SecurityFilterChain 인스턴스를 보여준다.

위의 그림에서 FilterChainProxy는 어떤 SecurityFilterChain을 사용할지 결정한다.
일치(match)하는 첫 번째 SecurityFilterChain만 호출된다.
만약 /api/messages/의 URL이 요청되면 먼저 SecurityFilterChain0 패턴의 /api/**와 일치하므로 SecurityFilterChain0만 호출된다.
만약 /messages/의 URL이 요청되면 /api/**의 SecurityFilterChain0 패턴과 일치하지 않으므로 FilterChainProxy는 각 SecurityFilterChain을 계속해서 시도한다.
일치하는 SecurityFilterChain 인스턴스가 없다고 가정하면, SecurityFilterChain n이 호출된다. (패턴이 /** 이기 때문)
SecurityFilterChain0은 3개의 Security Filter 인스턴스만 가지고 있다.
그러나 SecurityFilterChain n은 4개의 Security Filter 인스턴스를 가지고 있다.
각 SecurityFilterChain은 고유(unique)할 수 있으며 분리되어 구성될 수 있다.
실제로 application에서 Spring Security가 특정 요청을 무시하기를 원할 경우, SecurityFilterChain에는 0개의 Security Filter 인스턴스가 있을 수 있다.
Security Filters
Security Filter들은 SecurityFilterChain API를 통해 FilterChainProxy에 삽입된다.
이러한 Filter들은 인증(Authentication), 권한 부여(Authorization), 악용 방지(Exploit protection) 등 여러 가지 목적으로 사용될 수 있다.
Filter는 적절한 시기에 호출(invoke)되도록 보장하기 위해 특정 순서로 실행된다.
예를 들어, 인증(authentication)을 수행하는 Filter는 권한 부여(authorization)를 수행하는 Filter보다 먼저 호출되어야 한다.
일반적으로 Spring Security의 Filter 순서를 알 필요는 없다.
다만, 순서를 아는 것이 유익할 때가 있는데 알고 싶다면 FilterOrderRegistration 코드를 확인하면 된다.
위의 문단을 예시로 들기 위해 다음과 같은 Security configuration을 고려해보자.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(Customizer.withDefaults())
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults());
return http.build();
}
}
위의 설정 정보(configuration)는 다음과 같은 Filter 순서로 수행된다.
1. 먼저, CSRF 공격으로부터 보호하기 위해 CsrfFilter가 호출된다.
2. 요청을 인증(authenticate)하기 위해 Authentication Filter들이 호출된다.
3. AuthorizationFilter가 호출되어 요청을 승인한다.
Filter | Added by |
CsrfFilter | HttpSecurity#csrf |
UsernamePasswordAuthenticationFilter | HttpSecurity#formLogin |
BasicAuthenticationFilter | HttpSecurity#httpBasic |
AuthorizationFilter | HttpSecurity#authorizeHttpRequests |
HttpSecurity 클래스
HttpSecurity (Spring Security 4.0.4.RELEASE API)
Allows specifying which HttpServletRequest instances this HttpSecurity will be invoked on. This method allows for easily invoking the HttpSecurity for multiple different RequestMatcher instances. If only a single RequestMatcher is necessary consider using
docs.spring.io
참고 블로그
Servlet 이 뭐길래 Spring 할 때 알아야 할까? - 1
Spring Boot 에서 가장 중요한 개념 중 하나가 Servlet 이다. 왜 필요한지 알아보기 전, Servlet이 무엇인지부터 알아보자.
velog.io
https://toki0411.tistory.com/66
[spring] 서블릿(Servlet)이란?
목차 서블릿(Servlet)이란? 서블릿 컨테이너 JSP와 서블릿 1. 서블릿(Servlet)이란? 서블릿은 클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍
toki0411.tistory.com
https://catsbi.oopy.io/f9b0d83c-4775-47da-9c81-2261851fe0d0
스프링 시큐리티 주요 아키텍처 이해
목차
catsbi.oopy.io
Spring Security 공식 문서 - Architecture
https://docs.spring.io/spring-security/reference/servlet/architecture.html
Architecture :: Spring Security
The Security Filters are inserted into the FilterChainProxy with the SecurityFilterChain API. Those filters can be used for a number of different purposes, like authentication, authorization, exploit protection, and more. The filters are executed in a spec
docs.spring.io
Servlet Application
Spring Security는 표준 Servlet Filter를 사용하여 Servlet Container와 통합된다.
즉, Servlet Container에서 실행되는 모든 application과 함께 동작한다.
더 구체적으로 말하면, Spring Security의 이점을 활용하기 위해 Servlet-based application에서 Spring을 사용할 필요가 없다.
Filter란?
- HTTP 요청과 응답을 변경할 수 있는 재사용 가능한 코드
- 객체의 형태로 존재
- 클라이언트로부터 오는 요청(Request)과 최종 자원 사이에 위치하여 클라이언트의 요청 정보를 알맞게 변경 가능
- 최종 자원과 클라이언트로 가능 응답(Response) 사이에 위치하여 최종 자원의 요청 결과를 알맞게 변경 가능

- 자원이 받게 되는 요청 정보는 클라이언트와 자원 사이에 존재하는 필터에 의해 변경된 요청 정보가 된다.
- 클라이언트가 보게 되는 응답 정보는 클라이언트와 자원 사이에 존재하는 필터에 의해 변경된 응답 정보가 된다.
- 필터는 클라이언트와 자원 사이에 1개만 존재하는 경우가 보통이지만, 여러 개의 필터가 모여서 하나의 체인(chain)을 형성할 수 있다.
javax.servlet에 존재하는 Filter 인터페이스
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {
}
void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException;
default void destroy() {
}
}
Architecture
A Review of Filters
Spring Security의 Servlet 지원은 Servlet Filter를 기반으로 하기 때문에, Filter의 역할을 먼저 알아두는 것이 좋다.
다음 이미지는 하나의(single) HTTP 요청에 대한 handler의 일반적인 layering을 보여준다.

클라이언트는 application에 요청을 보내고, Container는 요청 URI의 경로를 기반으로 HttpServletRequest를 처리해야 하는 Filter 인스턴스와 Servlet을 포함하는 FilterChain을 생성한다.
Spring MVC application(응용 프로그램)에서 Servlet은 DispatcherServlet의 인스턴스이다.
많아야 하나의 Servlet이 하나의 HttpServletRequest 및 HttpServletResponse를 처리할 수 있다.
하지만, 둘 이상의 Filter를 사용하여 다음 작업을 수행할 수 있다.
- Downstream Filter 인스턴스 또는 Servlet이 호출되지 않도록 한다. (무슨 말인지 모르겠다.) 이 경우 Filter는 일반적으로 HttpServletResponse를 쓴다(write).
- Downstream Filter 인스턴스와 Servlet에서 사용하는 HttpServletRequest 또는 HttpServletResponse를 수정한다.
Filter의 힘은 FilterChain에서 나온다.
FilterChain Usage Example
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// do something before the rest of the application
chain.doFilter(request, response); // invoke the rest of the application
// do something after the rest of the application
}
Filter는 downstream Filter 인스턴스와 Servlet에만 영향을 미치기 때문에, 각 Filter가 호출되는 순서가 매우 중요하다.
(downstream이라는게 그 다음 순서를 의미하는 거 같기도 하다.)
DelegatingFilterProxy
: Servelt Filter를 구현한 Spring Bean에게 요청을 위임해주는 대리자 역할의 Servlet Filter

Spring은 Servlet container의 라이프 사이클과 Spring의 ApplicationContext 사이의 연결(bridging)을 허용하는 DelegatingFilterProxy라는 Filter 구현체를 제공한다.
Servlet Container는 자체 표준을 사용하여 Filter 인스턴스를 등록할 수 있지만, Spring이 정의한 Bean을 알지 못한다.
표준 Servlet Container 메커니즘을 통해 DelegatingFilterProxy를 등록할 수 있지만 Filter를 구현하는 Spring Bean에 모든 작업을 위임(delegate)할 수 있다.



다음은 DelegatingFilterProxy가 Filter 인스턴스들과 FilterChain에 어떻게 적용되어 있는지 보여주는 그림이다.

DelegatingFilterProxy는 ApplicationContext에서 Bean Filter0을 찾은 다음 Bean Filter0을 호출한다.
다음은 DelegatingFilterProxy의 pseudo code를 보여준다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
Filter delegate = getFilterBean(someBeanName); // (1)
delegate.doFilter(request, response); // (2)
}
(1) Spring Bean으로 등록된 Filter를 lazy하게 가져온다. 위의 코드에서 delegate는 Bean Filter0의 인스턴스이다.
(2) 작업을 Spring Bean에게 위임한다.
FilterProxy에 대한 모든 호출이 표준 Servlet Filter 인터페이스를 구현하는 데 필요한 Spring context의 해당 bean에 위임된다.
DelegatingFilterProxy의 또 다른 장점은 Filter bean 인스턴스 조회를 지연시킬 수 있다는 점이다.
이는 container가 시작하기 전에 Filter 인스턴스를 등록해야 하기 때문에 중요하다.
그러나, Spring은 일반적으로 ContextLoaderListener를 사용하여 Spring Bean을 등록(load)하는데, 이 작업은 Filter 인스턴스를 등록해야 할 때까지 수행되지 않는다.
FilterChainProxy
Spring Security의 Servlet 지원은 FilterChainProxy 내에 포함되어 있다.
FilterChainProxy는 SecurityFilterChain을 통해 많은 Filter 인스턴스들에게 위임할 수 있는 Spring Security에서 제공하는 특수한 Filter이다.
FilterChainProxy는 Bean이기 때문에 일반적으로 DelegatingFilterProxy로 감싸진다.



다음 이미지는 FilterChainProxy의 역할을 보여준다.

SecurityFilterChain
SecurityFilterChain은 FilterChainProxy에서 현재 요청에 대해 호출할 Spring Security의 Filter 인스턴스를 결정하는 데 사용된다.

다음 이미지는 SecurityFilterChain의 역할을 보여준다.

SecurityFilterChain의 Security Filter들은 일반적으로 Bean이지만, DelegatingFilterProxy가 아닌 FilterChainProxy에 등록되어 있다.
FilterChainProxy는 Servlet Container 또는 DelegatingFilterProxy에 직접 등록하는 데에 많은 이점을 제공한다.
2개의 이점은 너무 어려워서 공식 문서를 참고하자.
또한, SecurityFilterChain을 호출해야 하는 시기를 결정하는 데 더 많은 유연성을 제공한다.
Servlet Container에서 Filter 인스턴스는 URL에만 기반하여 호출되지만, FilterChainProxy는 RequestMatcher 인터페이스를 사용하여 HttpServletRequest에 있는 모든 것에 기반하여 호출을 결정할 수 있다.
다음 이미지는 여러 SecurityFilterChain 인스턴스를 보여준다.

위의 그림에서 FilterChainProxy는 어떤 SecurityFilterChain을 사용할지 결정한다.
일치(match)하는 첫 번째 SecurityFilterChain만 호출된다.
만약 /api/messages/의 URL이 요청되면 먼저 SecurityFilterChain0 패턴의 /api/**와 일치하므로 SecurityFilterChain0만 호출된다.
만약 /messages/의 URL이 요청되면 /api/**의 SecurityFilterChain0 패턴과 일치하지 않으므로 FilterChainProxy는 각 SecurityFilterChain을 계속해서 시도한다.
일치하는 SecurityFilterChain 인스턴스가 없다고 가정하면, SecurityFilterChain n이 호출된다. (패턴이 /** 이기 때문)
SecurityFilterChain0은 3개의 Security Filter 인스턴스만 가지고 있다.
그러나 SecurityFilterChain n은 4개의 Security Filter 인스턴스를 가지고 있다.
각 SecurityFilterChain은 고유(unique)할 수 있으며 분리되어 구성될 수 있다.
실제로 application에서 Spring Security가 특정 요청을 무시하기를 원할 경우, SecurityFilterChain에는 0개의 Security Filter 인스턴스가 있을 수 있다.
Security Filters
Security Filter들은 SecurityFilterChain API를 통해 FilterChainProxy에 삽입된다.
이러한 Filter들은 인증(Authentication), 권한 부여(Authorization), 악용 방지(Exploit protection) 등 여러 가지 목적으로 사용될 수 있다.
Filter는 적절한 시기에 호출(invoke)되도록 보장하기 위해 특정 순서로 실행된다.
예를 들어, 인증(authentication)을 수행하는 Filter는 권한 부여(authorization)를 수행하는 Filter보다 먼저 호출되어야 한다.
일반적으로 Spring Security의 Filter 순서를 알 필요는 없다.
다만, 순서를 아는 것이 유익할 때가 있는데 알고 싶다면 FilterOrderRegistration 코드를 확인하면 된다.
위의 문단을 예시로 들기 위해 다음과 같은 Security configuration을 고려해보자.
@Configuration
@EnableWebSecurity
public class SecurityConfig {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.csrf(Customizer.withDefaults())
.authorizeHttpRequests(authorize -> authorize
.anyRequest().authenticated()
)
.httpBasic(Customizer.withDefaults())
.formLogin(Customizer.withDefaults());
return http.build();
}
}
위의 설정 정보(configuration)는 다음과 같은 Filter 순서로 수행된다.
1. 먼저, CSRF 공격으로부터 보호하기 위해 CsrfFilter가 호출된다.
2. 요청을 인증(authenticate)하기 위해 Authentication Filter들이 호출된다.
3. AuthorizationFilter가 호출되어 요청을 승인한다.
Filter | Added by |
CsrfFilter | HttpSecurity#csrf |
UsernamePasswordAuthenticationFilter | HttpSecurity#formLogin |
BasicAuthenticationFilter | HttpSecurity#httpBasic |
AuthorizationFilter | HttpSecurity#authorizeHttpRequests |
HttpSecurity 클래스
HttpSecurity (Spring Security 4.0.4.RELEASE API)
Allows specifying which HttpServletRequest instances this HttpSecurity will be invoked on. This method allows for easily invoking the HttpSecurity for multiple different RequestMatcher instances. If only a single RequestMatcher is necessary consider using
docs.spring.io
참고 블로그
Servlet 이 뭐길래 Spring 할 때 알아야 할까? - 1
Spring Boot 에서 가장 중요한 개념 중 하나가 Servlet 이다. 왜 필요한지 알아보기 전, Servlet이 무엇인지부터 알아보자.
velog.io
https://toki0411.tistory.com/66
[spring] 서블릿(Servlet)이란?
목차 서블릿(Servlet)이란? 서블릿 컨테이너 JSP와 서블릿 1. 서블릿(Servlet)이란? 서블릿은 클라이언트의 요청을 처리하고, 그 결과를 반환하는 Servlet 클래스의 구현 규칙을 지킨 자바 웹 프로그래밍
toki0411.tistory.com
https://catsbi.oopy.io/f9b0d83c-4775-47da-9c81-2261851fe0d0
스프링 시큐리티 주요 아키텍처 이해
목차
catsbi.oopy.io