뭐라도 끄적이는 BLOG

Spring Security Architecture 본문

SpringFramework/Spring Security

Spring Security Architecture

Drawhale 2023. 7. 18. 21:43

Servlet Filtes

Spring Security는 Servlet Filter를 기반으로 Servlet을 지원하므로, Filter의 역할을 살펴보는 것이 이해에 도움이 된다. 다음 이미지는 단일 HTTP 요청을 처리하는 일반적인 레이어를 보여준다.

클라이언트가 어플리케이션에 요청을 보내면 컨테이너는 요청 URI Path를 기반으로 HttpServletRequest를 처리해야 하는 Filter로 구성된 FilterChain을 생성한다. Spring MVC 어플리케이션에서 Servlet은 DispatcherServlet 인스턴스이다. 단일 HttpServletRequest 및 HttpServletResponse처리는 최소 하나의 Servlet이 담당한다. 하지만 둘 이상의 Filter를 사용할 수 있다. Filter는 보통 아래와 같이 사용한다.

  • 다운스트림의 Servlet과 여러 Filter의 실행을 막는다. 이 경우 Filter는 일반적으로 HttpServletResponse를 작성한다.
  • 다운스트림의 Servlet과 여러 FIlter인스턴스로 HttpServletRequest 또는 HttpServletResponse를 수정한다.

Filter는 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
}

Filter는 다운스트림에 있는 나머지 Filter 인스턴스와 Servlet에만 영향을 미치므로 각 Filter가 호출되는 순서가 매우 중요하다.

DelegatingFilterProxy

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

다음은 DelegatingFIlterProxy가 여러 Filter로 구성된 FilterChain에 어떻게 적용되는지 보여주는 그림이다.

DelegatingFilterProxy는 ApplicationContext에서 Bean Filter0을 조회한 다음 Bean Filter0을 호출한다. 다음은 DelegatingFilterProxy의 의사 코드를 보여준다.

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
	Filter delegate = getFilterBean(someBeanName);
	// Spring Bean으로 등록된 Filter를 느리게 가져온다.
	// 예제에서 DelegatingFilterProxy는 Bean Filter0.delegate의 인스턴스이다.
	delegate.doFilter(request, response); 
	// 스프링 빈에 작업을 위임한다.
}

DelegatingFilterProxy의 또 다른 이점은 Filter 빈 인스턴스 조회를 지연시킬 수 있다는 것이다. 이는 컨테이너가 시작되기 전에 Filter 인스턴스를 등록해야 하기 때문에 중요하다. 그러나 Spring은 일반적으로 ContextLoaderListener를 사용하여 Spring Bean을 로드하는데, 이 작업은 Filter 인스턴스를 등록한 후에야 수행된다.

FilterChainProxy

Spring Security는 FilterChainProxy로 Servlet을 지원한다. FilterChainProxy는 Spring Security에서 제공하는 특별한 Filter로, SecurityFIlterChain을 통해 많은 FIlter인스턴스로 위임할 수 있다. FilterChainProxy는 Bean이기 때문에 일반적으로 DelegatingFilterProxy로 감싸져있다.

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

SecurityFilterChain

FilterChainProxy가 요청에 사용할 Spring Security의 Filter들을 선택할 때 SecurityFilterChain을 사용한다.

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

SecurityFilterChain의 Security Filter들은 일반적인 Bean이지만, DelegatingFilterProxy가 아닌 FilterChainProxy에 등록된다. FilterChainProxy를 서블릿 컨테이너에 등록하거나 DelegatingFilterProxy에 직접 등록하는 것은 여러 가지 이점을 제공한다.

  1. Spring Security가 Servlet을 지원할 수 있는 시작점이 되어준다. 따라서 Servlet에 Spring Security를 정용하다 문제를 겪는다면 FilterChainProxy 부터 디버그 포인터를 추가해 보는 것이 좋다.
  2. FilterChainProxy는 Spring Security 사용의 핵심이므로 필수로 여겨지는 작업을 수행할 수 있다. 예를 들어, 메모리 누수를 방지하기 위해 SecurityContext를 비울 수 있다. 또한 특정 유형의 공격으로부터 애플리케이션을 보호하기 위해 Spring Security의 HttpFirewall을 적용할 수 있다.
  3. SecurityFilterChain을 호출해야 하는 시기를 보다 유연하게 결정할 수 있다. 서블릿 컨테이너에서 Filter 인스턴스는 URL만을 기반으로 호출된다. 그러나 FilterChainProxy는 RequestMatcher 인터페이스를 사용하여 HttpServletRequest에 있는 모든 것을 기반으로 호출을 결정할 수 있다.

다음 이미지는 여러 SecurityFilterChain 인스턴스를 보여준다

Multiple SecurityFilterChain 그림에서 FilterChainProxy는 어떤 SecurityFilterChain을 사용할지 결정한다. 가장 먼저 일치하는 SecurityFilterChain가 호출된다.

만약 /api/messages/의 URL을 요청하면, SecurityFilterChain0의 /api/** 패턴과 가장 먼저 매칭되어, 다른 SecurityFilterChain에서도 일치하더라도 SecurityFilterChain0만 호출된다. /message/의 URL이 요청되면 SecurityFilterChain0의 /api/** 패턴과 일치하지 않으므로 FilterChainProxy는 각 SecurityFilterChain을 계속 시도한다. 매칭되는 SecurityFilterChain 인스턴스가 없다고 가정하면 SecurityFilterChainn이 호출된다.

SecurityFilterChain0에는 세 개의 보안 필터 인스턴스만 구성되어 있다. 그러나 SecurityFilterChainn에는 4개의 보안 필터 인스턴스가 구성되어 있다. 각 SecurityFilterChain은 고유한 설정을 가질 수 있으며 개별적으로 구성할 수 있다는 점에 유의해야 한다. 사실, 애플리케이션에서 Spring Security가 특정 요청을 무시하기를 원하는 경우 SecurityFilterChain에 보안 필터 인스턴스를 0개로 설정할 수 있다.

Security FIlters

보안 필터는 SecurityFilterChain API를 사용하여 FilterChainProxy에 삽입된다. 필터 인스턴스의 순서는 중요하다. 일반적으로 Spring Security의 Filter 인스턴스 순서를 알 필요는 없다. 그러나 순서를 아는 것이 도움이 되는 경우가 있다.

다음은 Spring Security 필터 순서에 대한 목록이다:

  • ForceEagerSessionCreationFilter
  • ChannelProcessingFilter
  • WebAsyncManagerIntegrationFilter
  • SecurityContextPersistenceFilter
  • HeaderWriterFilter
  • CorsFilter
  • CsrfFilter
  • LogoutFilter
  • OAuth2AuthorizationRequestRedirectFilter
  • Saml2WebSsoAuthenticationRequestFilter
  • X509AuthenticationFilter
  • AbstractPreAuthenticatedProcessingFilter
  • CasAuthenticationFilter
  • OAuth2LoginAuthenticationFilter
  • Saml2WebSsoAuthenticationFilter
  • UsernamePasswordAuthenticationFilter
  • DefaultLoginPageGeneratingFilter
  • DefaultLogoutPageGeneratingFilter
  • ConcurrentSessionFilter
  • DigestAuthenticationFilter
  • BearerTokenAuthenticationFilter
  • BasicAuthenticationFilter
  • RequestCacheAwareFilter
  • SecurityContextHolderAwareRequestFilter
  • JaasApiIntegrationFilter
  • RememberMeAuthenticationFilter
  • AnonymousAuthenticationFilter
  • OAuth2AuthorizationCodeGrantFilter
  • SessionManagementFilter
  • ExceptionTranslationFilter
  • AuthorizationFilter
  • SwitchUserFilter
반응형

'SpringFramework > Spring Security' 카테고리의 다른 글

Custom UserDetailsService & Custom User  (0) 2023.07.10
Multiple SecurityChain  (0) 2023.07.09
Spring Security OAuth(Google)  (0) 2023.07.09
Spring Security Embedded H2 Database 사용 방법  (0) 2023.07.08
Security Configuration  (0) 2023.07.07