Spring Security란?
입증, 권한, 그리고 흔한 공격에 대한 방어적 기술을 제공하는 프레임워크이다.
1. 입증이란 특정 리소스에 접근하는 사용자의 신원을 어떻게 증명할 것인지에 대한 부분이다. 가장 흔한 입증 방식은 유저에게 이메일과 패스워드를 입력하게 하는 방식이다.
2. 이런 입증과정을 통해 입증이 되면, 사용자는 권한을 행사할 수 있게 된다. (특정 리소스에 접근할 수 있음)
Spring Security와 Servlet Applications
스프링 시큐리티는 Servlet의 Filter를 사용함으로써 Servlet 컨테이너를 지원한다. 따라서 Servlet을 사용하는 모든 어플리케이션에서 스프링 시큐리티를 사용할 수 있다.
Architecture
Servlet을 기반으로 한 어플리케이션에서 스프링 시큐리티의 아키텍쳐를 살펴보자.
스프링 시큐리티의 서블릿 제공은 Servlet의 Filter에 기반한다. 따라서 Servlet Filter의 역할을 먼저 살펴볼 필요가 있다. 다음 그림은 싱글 HTTP 요청이 들어왔을 때, 일반적인 핸들러 계층이다.
클라이언트가 애플리케이션에 요청을 보내면, 컨테이너는 Filter와 Servlet을 포함하고 있는 FilterChain을 생성한다. 보통 Servlet은 한 개의 HttpServletRequest와 HttpServletResponse를 다루지만, 한 개 이상의 필터도 사용되어질 수 있다.
[FilterChain 사용 예시]
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
}
DelegatingFilterProxy
Servlet 컨테이너는 서로 다른 기준을 가진 Filter를 등록하는 것을 허용하지만, 스프링은 이를 Beans으로 인식하지 못한다. 스프링은 Servlet 컨테이너의 생명주기와 스프링의 ApplicationContext를 연결하기 위해서, DelegatingFilterProxy라는 Filter implementation을 제공한다.DelegatingFilterProxy는 표준 Servlet 컨테이너 메커니즘을 통해 등록되어지나, 모든 작업을 스프링 빈으로도 등록하기 때문에 스프링이 이를 인식할 수 있다.
DelegatingFilterProxy는 ApplicationContext로부터 Bean Filter_0을 찾은 다음, Bean Filter_0를 호출한다.
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
// Lazily get Filter that was registered as a Spring Bean
// For the example in DelegatingFilterProxy
delegate
is an instance of Bean Filter0
Filter delegate = getFilterBean(someBeanName);
// delegate work to the Spring Bean
delegate.doFilter(request, response);
}
DelegatingFilterProxy의 또 다른 이점은 Filter bean 객체를 찾는 것을 지연시킬 수 있다는 점이다. 컨테이너는 Filter 객체를 컨테이너가 시작하기 전에 등록할 필요가 있는데, 스프링에서 빈을 불러오기 위해 사용하는 ContextLoaderListener는 Filter 객체가 필요할 때 까지 등록하지 않는다.
FilterChainProxy
스프링 시큐리티의 서블릿은 FilterChainProxy안에서 지원을 받는다. FilterChainProxy는 많은 필터 객체가 SecurityFilterChain으로 전파될 수 있도록 도와주는 특별한 필터이다. FilterChainProxy가 bean이기 때문에, 전형적으로 DelegatingFilterProxy에 감싸져 있다.
SecurityFilterChain
SecurityFilterChain은 어떤 스프링 시큐리티 필터를 사용할지 결정하기 위해 FilterChainProxy와 소통한다. SecurityFilterChain도 FilterChainProxy와 마찬가지로 빈이지만, DelegatingFilterProxy가 아닌 FilterChainProxy와 함께 등록이 되어 있다.
FilterChainProxy는 많은 이점을 제공하고 있다.
1. 모든 스프링 시큐리티의 서블릿 지원에게 시작점을 제공한다. (FilterChainProxy에 debug 포인트를 찍는 것은 디버깅을 쉽게 도와줄 것이다.)
2. FilterChainProxy가 스프링 시큐리티 사용의 중심에 있기 때문에, 메모리 유출을 피하는 등의 SecurityContext를 분명히 하는 역할을 한다.
3. SecurityFilterChain이 언제 호출되어야 하는지에 대한 부분에 있어 유연성을 제공한다. 필터에서는 URL에 기반해서 호출이 되지만, FilerChainProxy는 HttpServletRequest의 어떤 요소든지 기준점을 잡고 호출할 수 있다.
4. FilterChainProxy는 여러개의 SecurityFilterChain이 있을 때 어떤 SecurityFilterChain이 언제 사용되어져야하는지를 지정하는데 사용되어질 수 있으면 이는 큰 이점을 가진다.
만약에 URL로 /api/messages/가 요청으로 들어오면, FilterChainProxy는 SecurityFilterChain_0을 먼저 매칭할 것이다. 그러면 SecurityFilterChain_n도 매칭이 됨에도 불구하고 _0번만 호출이 된다.