Spring

[Spring Security] 스프링 시큐리티 아키텍처

림 림 2020. 12. 27. 14:16
반응형

1. 필터(Filter)

스프링 시큐리티는 서블릿의 필터를 기반으로 동작합니다.

일반적으로 클라이언트에서 서버로 요청을 보내면, DispatcherServlet이라는 서블릿이 하나의 HttpServeletRequest를 받아서 요청을 처리하고 HttpServletResponse 응답을 클라이언트로 보냅니다.

그런데, 하나 이상의 필터가 포함된다면, 클라이언트에서 보낸 요청이 서블릿으로 전달되기 전에 필터를 거치게 됩니다.

FilterChain

클라이언트가 애플리케이션에 하나의 요청을 보내면, 컨테이너는 하나의 필터 체인(FilterChain)을 생성합니다.
필터 체인에는 필터와 서블릿이 들어 있습니다.

필터 체인 내부의 필터는 말 그대로 '필터'의 역할을 하게 됩니다.
클라이언트에서 보낸 요청이 다음 필터나 서블릿에 전달되지 않도록 걸러낼 수 있습니다.

필터에서 요청이 다음으로 전달되지 못하도록 걸러냈을 경우에는 필터 내부에서 HttpServletResponse를 만들어 서블릿 대신에 클라이언트에 응답을 보낼 수 있습니다.
요청이 다음으로 전달되게 할 경우에는 HttpServletRequest나 HttpServletResponse의 내용을 변경하여 가공된 데이터를 다음 필터나 서블릿에 전달할 수 있습니다.

 

2. DelegatingFilterProxy

사용자의 요청이 서블릿에 전달되어 자원에 접근하기 전에, 스프링 시큐리티는 필터의 생명주기를 이용해서 인증과 권한 작업을 수행합니다.
서블릿 필터의 생명주기 시점에서 스프링 시큐리티에서 동작하는 인증과 권한 작업을 수행해야 하는데, 서블릿 컨테이너에서는 스프링 컨테이너에 등록된 빈을 인식할 수 없습니다.

따라서 스프링 시큐리티에서는 DelegatingFilterProxy라는 서블릿 필터의 구현체를 제공합니다.
DelegatingFilterProxy는 서블릿 매커니즘을 통해 서블릿의 필터로 등록될 수 있으며 스프링에 등록된 빈을 가져와 의존성을 주입할 수 있습니다.
이렇게 DelegatingFilterProxy는 서블릿 컨테이너의 생명주기와 스프링의 ApplicationContext 사이를 연결하는 다리 역할을 하게 됩니다.

DelegatingFilterProxy

DelegatingFilterProxy에서는 서블릿 필터에서 받은 요청과 응답을 스프링 빈으로 등록된 필터로 전달합니다.

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에서는 getFilterBean()을 통해 ApplicationContext을 통해 빈으로 등록된 필터를 가져옵니다.
그리고 나서 DelegatingFIlterProxy가 받은 요청과 응답 객체를 빈으로 등록된 필터의 doFilter()에 넘겨주면서 빈으로 등록된 필터의 작업을 실행시킵니다.

 

3. FilterChainProxy

DelegatingFilterProxy의 내부에는 FilterChainProxy라는 것이 있는데, 이것도 스프링 시큐리티에서 제공하는 필터입니다.

FilterChainProxy는 DelegatingFilterProxy를 통해 받은 요청과 응답을 스프링 시큐리티 필터 체인에 전달하고 작업을 위임하는 역할을 합니다.

DelegatingFilterProxy에서 바로 SecurityFilterChain을 실행시킬 수도 있지만, 중간에 FilterChainProxy를 두는 이유는 바로 서블릿을 지원하는 시작점 역할을 하기 위해서입니다.
만약 서블릿에서 문제가 발생한다면 FilterChainProxy의 문제라는 것을 바로 알 수 있습니다.

또, 뒤에서 살펴보겠지만 시큐리티 필터 체인은 여러 개로 구성되는 경우도 있습니다. 이때, DelegatingFIlterProxy에는 FilterChainProxy 하나만 두고, 선택적으로 여러 개의 시큐리티 필터 체인을 구성함으로써 FilterChainProxy가 어떤 필터 체인에게 작업을 위임할지 결정할 수도 있습니다.

FilterChainProxy

 

4. SecurityFilterChain

SecurityFilterChain은 인증을 처리하는 여러 개의 시큐리티 필터를 담는 필터 체인입니다. 또, 필터체인 프록시를 통해 서블릿 필터와 연결되고 어떤 시큐리티 필터를 통해 인증을 수행할지 결정하는 역할을 합니다.

SecurityFilterChain

여러 개의 SecurityFilterChain을 구성하여 매칭되는 URL에 따라 다른 SecurityFilterChain이 사용되도록 할 수도 있습니다.

 

5. Security Filters

시큐리티 필터는 요청을 스프링 시큐리티 매커니즘에 따라 처리하는 필터입니다.
앞에서 본 DelegatingFilterProxy와 FilterChainProxy가 서블릿과 스프링과의 연결을 담당했다면, Security Filter는 시큐리티의 핵심 기능을 수행하는 지점입니다.

시큐리티 필터는 SecurityFilterChain API를 통해 FilterChainProxy에 삽입되고 스프링 빈으로 등록됩니다.

시큐리티 필터들에는 순서가 존재합니다. 자세한 시큐리티 필터의 종류와 순서는 다음 링크를 참고하시면 됩니다.

docs.spring.io/spring-security/site/docs/5.4.2/reference/html5/#servlet-security-filters

 

Spring Security Reference

In Spring Security 3.0, the codebase was sub-divided into separate jars which more clearly separate different functionality areas and third-party dependencies. If you use Maven to build your project, these are the modules you should add to your pom.xml. Ev

docs.spring.io

 

반응형