💡 개요
Spring Security를 공부하면서, Spring Boot와 Spring Data JPA를 공부했을 때보다 뭔가 확 와닿는 느낌이 부족했다.
필자가 생각하기에는 Spring Security의 동작 과정이나 내부에서 통상적으로 사용되는 용어의 의미를 정확히 이해하고 있지 않아서라고 판단했다.
따라서 이번 기회에 사전 지식이나 내부 로직 등을 확실히 이해하고, 정리해 보고자 한다.
📘 사전지식
통상적인 용어 개념
- Authentication : 해당 사용자가 본인인지 확인하는 절차 (인증)
- Authorization : 특정 페이지나 자원에 접근 가능한지 결정할 수 있는 요소 (인가 혹은 권한)
- Principal : 인증 대상 (아이디 등..)
- Credential : 인증을 받기위해 필요한 정보 (비밀번호 등..)
- details : 인증 부가 정보
ContextLoaderListener vs DispatcherServlet
ContextLoaderListener
- 루트 ApplicationContext를 생성하는 클래스
ContextLoaderListener
의 ApplicationContext에는 서비스, 저장소, 인프라 빈 등과 같이 전역적으로 볼 수 있는 Bean이 포함되어 있다. 루트 ApplicationContext가 생성된 후 ServletContext에 속성으로 저장된다.
DispatcherServlet
- Front Controller이며, 기본적으로 구성된 URL 패턴과 일치하는 수신 웹 요청을 처리하는 것이 주 목적인 서블릿이다.
- HttpServlet을 상속하고 있다.
(DispatcherServlet -> FrameworkServlet -> HttpServletBean -> HttpServlet)
특징
- Spring은 한번에 여러 컨텍스트를 가질 수 있으며, 그 중 하나는 루트 ApplicationContext가 되고, 다른 모든 ApplicationContext는 자식 ApplicationContext가 된다.
- 루트 ApplicationContext는
ContextLoaderListener
에 의해 생성되며, 나머지 자식 ApplicationContext들은 DispatcherServlet
에 의해 생성된다.
- 자식 ApplicationContext는 루트 ApplicationContext에 정의된 Bean에 액세스할 수 있으나, 루트 ApplicationContext의 Bean은 자식 ApplicationContext의 Bean에 직접 액세스할 수 없다.
- 일반적으로, Spring MVC 관련 컴포넌트는
DispatcherServlet
의 ApplicationContext 인터페이스에서 초기화되고, 나머지는 ContextLoaderListener
에 의해 로드된다.
- Spring Security의 모든 설정은
ContextLoaderListener
에 의해 초기화된다.
DelegatingProxyChain
개념
- Spring Web에서 제공하는 Servlet Filter
- 루트 ApplicationContext의 Spring Beans에게 모든 요청을 위임해주는 역할
사용과정
- Servlet Filter는 Spring에서 정의된 Bean을 주입해서 사용할 수 없으므로 (Servlet Filter는 Servlet Container가 관리하고 Spring Bean은 Spring Container가 관리하므로)
Servlet Filter는 DelegatingFilterProxy
를 이용하여 Spring Container에 존재하는 springSecurityFilterChain
이라는 Bean을 찾아 요청을 위임한다.
FilterChainProxy
개념
DelegatingFilerProxy
로 부터 요청 위임을 받고 실제 보안요소들을 처리하는 역할이다.
- SecurityFilterChain 인스턴스 목록을 사용하여 구성되며, 각 인스턴스에는 RequestMatcher와 일치하는 요청에 적용해야 하는 필터 목록이 포함되어 있다.
- Spring Security 초기화 시 생성되는 필터들을 관리하고 제어하는 역할이다.
- 다양한 Filter를 통해 인증과 인가 및 각종 요청에 대한 처리를 수행한다.
📌 Spring Security
개념
- 애플리케이션의 보안(인증과 권한)에 대한 부분을 Filter를 이용하여 처리하는 Spring의 하위 Framework이다.
- 인증과 권한 부여를 분리하여 설계된 아키텍처를 가지고 있다. 또한 인증과 권한 부여에 대한 strategy를 가지고 있으며 확장도 가능하다.
동작 과정
- 클라이언트의 Request
- Servlet Container의 Filter들이 처리를 진행하고,
DelegatingFilterProxy
가 요청을 받게된다.
- Spring Container에서
springSecurityFilterChain
이라는 이름을 가진 Bean을 찾는다. 이때 클라이언트의 요청을 위임받을 객체는 FilterChainProxy
이다.
DelegatingFilterProxy
는 클라이언트의 요청을 위임하고, 해당 요청은 FilterChainProxy
의 doFilter() 메서드로 넘어간다.
FilterChainProxy
에서 해당 요청을 처리할 SecurityFilterChain
을 찾는다.
(FilterChainProxy
가 저장하고 있는 SecurityConfig
객체들에서 클라이언트가 요청한 URL 정보와 매치되는 객체를 찾는다)
- 일치하는
SecurityFilterChain
의 Security Filter를 순서대로 거쳐 인증 및 인가처리를 진행한다.
📌 Spring Security의 Filters
특징
- Spring Security의 Filter들은 각기 다른 역할을 수행한다.
- 필요한 Filter만 적용할 수 있으며, Filter들의 순서를 조정할 수 있다.
종류
SecurityContextPersistenceFilter
SecurityContextRepository에서 SecurityContext를 가져와 유저의 Authentication에 접근할 수 있도록 하는 Filter
LogoutFilter
로그아웃 요청을 처리하는 Filter
UsernamePasswordAuthenticationFilter
ID와 PW를 사용하는 Form기반 유저 인증을 처리하는 Filter
DefaultLoginPageGeneratingFilter
커스텀 로그인 페이지를 지정하지 않았을 경우, 기본 로그인 페이지를 반환하는 Filter
AnonymousAuthenticationFilter
이 Filter가 호출되는 시점까지 사용자가 인증되지 않았다면, 익명 사용자 토큰을 반환하는 Filter
ExceptionTranslationFilter
Filter Chain 내에서 발생된 모든 예외를 처리하는 Filter
FilterSecurityInterceptor
권한 부여와 관련된 결정을 AccessDecisionManager에게 위임해 권한 부여 및 접근 제어를 처리하는 Filter
RequestCacheAwareFilter
로그인 성공 후, 이전 요청 정보를 재구성 하기위해 사용하는 Filter
SessionManagementFilter
로그인 이후 인증된 사용자인지 확인하거나, 설정된 세션의 메커니즘에 따라 작업을 수행하는 Filter
BasicAuthenticationFilter
HTTP 요청의 인증 헤더를 처리하여 결과를 SecurityContextHolder에 저장하는 Filter
RememberMeAuthenticationFilter
세션이 사라지거나 만료 되더라도 쿠키 또는 DB를 사용하여 저장된 토큰 기반으로 인증을 처리하는 Filter
❗️ 아직 내용이 조금 빈약하지만, 더 공부해 나가면서 채울 예정입니다 😄
🏴 Reference
spring.io - Spring Security Architecture
docs.spring.io - Class FilterChainProxy
Spring Security 3/e (스프링 시큐리티를 이용한 애플리케이션 보안)
HowToDoInJava - ContextLoaderListener vs DispatcherServlet
Catsbi's DLog - 스프링 시큐리티 주요 아키텍처 이해