Spring Security 공식 문서 톺아보기(1)
스프링 부트 Auto Configuration
스프링 부트 Auto Configuration이 아래와 같은 작업을 진행
- 스프링 시큐리티 기본 설정
springSecurityFilterChain이라는 서블릿filter를 bean으로 생성- 이
springSecurityFilterChain은 어플리케이션의 모든 security와 관련된 책임을 수행
- username, 랜덤하게 생성된 password 갖는
UserDtailsService라는 이름의 bean을 생성
아키텍처
Filter Chain 구성 - 서블릿 컨테이너
스프링 시큐리티의 서블릿 지원은 Servlet Filter를 기반으로 함
클라이언트가 요청을 어플리케이션에 전달하면 컨테이너는 FilterChain을 생성하는데, 이 체인은 HttpServeltRequest를 처리하기 위한 Filter와 Servlet들을 담고 있음
하나의 Filter는 다음 호출되는 Filter 또는 Servlet에게만 영향을 미치기 때문에 Filter의 호출 순서가 매우 중요
DelegatingFilterProxy(중요. 스프링과 관련(스프링 시큐리티 아님))
스프링은 DelegatingFilterProxy라는 Filter를 제공하는데 (중요) 서블릿 컨테이너의 lifecycle과 스프링의 ApplicationContext의 브릿지 역할을 한다.
서블릿 컨테이너는 자체 표준 메커니즘에 따라Filter들을 등록할 수 있는데Spring Bean에 대한 정보가 없기 때문에Filter로 등록하기 위한Spring Bean을 알 수 없다.
하지만 DelegatingFilterProxy는 서블릿 컨테이너의 표준 메커니즘에 따라 Filter로 등록될 수 있다.
그런데 Servlet Container와 Spring ApplicationContext의 Bridge 역할을 한다는 점에 주목하자.
서블릿 컨테이너의 Filter에 등록되었지만 Spring Bean이고 주 역할은 Filter를 구현하는 다른 Spring Bean에게 작업을 위임함으로써 Bridge 역할을 하는 것
Bean Filter인 DelegatingFilterProxy는 ApplicationContext에서 관리되는 다른 Bean Filter들을 look up하고 실행(위임)한다.
대략적인 DelegatingFilterProxy의 역할을 나타내는 ‘슈도 코드’
FilterChainProxy (중요, 스프링 시큐리티와 관련)
스프링 시큐리티의 서블릿 지원은 FilterChainProxy에 포함된다.
(중요)
FilterChainProxy는 스프링 시큐리티가 제공하는 특별한Bean Filter인데,SecurityFilterChain을 통해 다양한 Filter 인스턴스들에게 위임을 한다.
FilterChainProxy는 Bean이기 때문에 DelegateFilterProxy에 래핑된다.
SecurityFilterChain (가장 중요, 스프링 시큐리티의 시작이자 근간)
SecurityFilterChain은 위에서 설명한 FilterChainProxy에 의해 사용된다.
즉, 현재 클라이언트의 요청에 대해서 어떤 Spring Security Filter가 호출될지가 FilterChainProxy에 의해 결정된다.
SecurityFilterChain 내의 Security Filter들은 Spring Bean이지만 DelegatingFilterProxy가 아니라 FilterChainProxy에 등록된다.
FilterChainProxy가 등록하는 것이 Servlet Container나 DelegateingFilterProxy가 등록하는 것 보다 더 좋은 점이 있다.
- 모든
Spring Security의 서블릿 지원의 시작점을 제공한다.- 따라서 만일
스프링 시큐리티 서블릿 지원과 관련한 트러블 슈팅을 할 때FilterChainProxy에서 디버깅을 시작하면 된다.
- 따라서 만일
- 언제
SecurityFilterChain이 실행될지와 관련해서 더 많은 유연성을 제공한다.- Servlet Container 내에서 Filter는 요청 URL과 관련해서만 호출된다. 하지만
FilterChainProxy는HttpServletRequest와 관련된 어떤 정보로든 호출 여부를 결정할 수 있다.
- Servlet Container 내에서 Filter는 요청 URL과 관련해서만 호출된다. 하지만
실제로 FilterChainProxy는 어떤 SecurityFIlterChain이 사용되어야 하는지를 결정하기 위해 사용된다. 이는 어플리케이션의 다른 설정들과 독립된 설정을 제공한다.
Multiple SecurityFilterChain
만일 SecurityFilterChain이 여러 개 있다면, FilterChainProxy는 어떤 SecurityFilterChain을 사용할지 결정한다.
조건에 맞는 chain들이 여러개 있다면 첫 번째로 만족한 chain을 사용한다.
Security Filters
Sercurity Filter들은 SecurityFilterChain API를 사용하여 FilterChainProxy에 주입된다.
Filter의 순서가 중요하다.
굳이 다 외울 필요는 없지만 스프링 시큐리티의 Filter들은 아래의 순서를 갖는다.
- ChannelProcessingFilter
- WebAsyncManagerIntegrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- CorsFilter
- CsrfFilter
- LogoutFilter
- OAuth2AuthorizationRequestRedirectFilter
- Saml2WebSsoAuthenticationRequestFilter
- X509AuthenticationFilter
- AbstractPreAuthenticatedProcessingFilter
- CasAuthenticationFilter
- OAuth2LoginAuthenticationFilter
- Saml2WebSsoAuthenticationFilter
[UsernamePasswordAuthenticationFilter](https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/form.html#servlet-authentication-usernamepasswordauthenticationfilter)- OpenIDAuthenticationFilter
- DefaultLoginPageGeneratingFilter
- DefaultLogoutPageGeneratingFilter
- ConcurrentSessionFilter
[DigestAuthenticationFilter](https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/digest.html#servlet-authentication-digest)- BearerTokenAuthenticationFilter
[BasicAuthenticationFilter](https://docs.spring.io/spring-security/reference/servlet/authentication/passwords/basic.html#servlet-authentication-basic)- RequestCacheAwareFilter
- SecurityContextHolderAwareRequestFilter
- JaasApiIntegrationFilter
- RememberMeAuthenticationFilter
- AnonymousAuthenticationFilter
- OAuth2AuthorizationCodeGrantFilter
- SessionManagementFilter
[ExceptionTranslationFilter](https://docs.spring.io/spring-security/reference/servlet/architecture.html#servlet-exceptiontranslationfilter)[FilterSecurityInterceptor](https://docs.spring.io/spring-security}/reference/servlet/authorization/authorize-requests.html#servlet-authorization-filtersecurityinterceptor)- SwitchUserFilter
Handling Security Exceptions
ExceptionTranslationFilter는 AccessDeniedException과 AuthenticationException을 HttpResponse의 결과로 변환해주는 역할을 수행한다.
물론 ExceptionTranslationFilter는 Security Filter들 중 하나로 FilterChainProxy에 내부에 삽입되어 사용된다.
ExceptionTransaltionFilter는 어플리케이션 프로세스 수행을 위해FilterChain.doFilter(request, response)호출- 만일 유저가 아직 인증되지 않았거나
AuthenticationException발생 시, 인증 프로세스 시작SecurityContextHolder가 clear됨HttpServletRequest가RequestCache에 저장- 만일 유저가 정상적으로 인증되었다면
RequestCache에서 원래HttpServletRequest를 꺼내서 프로세스 진행
- 만일 유저가 정상적으로 인증되었다면
AuthenticationEntryPoint가 클라이언트의 요청 자격 증명을 위해 사용됨 (로그인 페이지로 redirect를 하거나 등
- 만일
AccessDeniedException발생 시 접근 거부로 간주하여AccessDeniedHandler가 호출됨
ExceptionTranslationFilter의 슈도 코드