개발 일지

Spring/Spring Security

스프링 컨테이너에서 동작하는 spring security에 등록된 필터가 어떻게 http 요청을 가로채서 처리하는 필터의 역할을 수행할 수 있을까?(Servlet Container, Spring Container, DelegatingFilterProxy)

junjun_ 2024. 9. 20. 16:50
 

Spring Security 인증 동작 과정(2) - Filter

저번 글에서 Spring Security가 무엇이고 인증에 대한 기본 동작에 대해서 살펴보았다.Spring Security는 필터를 기반으로 동작한다고 했었는데, 이번글에서는 이 Filer에 대해 알아보고 실재 코드를 보면

jueun275.tistory.com

 

이전글에서 Spring Security와 Filter에 대해 간단하게 정리를 한 번 했었는데요. 이전글은 springsecurityfilter 체인에 대에 초점을 맞추었다면 이번글에서는 잠깐 다루었던 DelegatingFilterProxy에 대해 정리해 보려고 합니다.

 스프링 컨테이너에서 동작하는 spring security에 등록된 필터가 어떻게 http 요청을 가로채서 처리하는 필터의 역할을 수행할 수 있을까?

 

이번글에서는 이 질문에 대한 답을 정리해보면서 Spring Security와 DelegatingFilterProxy에 대해 더 자세하게 알아보도록 하겠습니다.

 


1. Spring Security와 Servelt Filter 

Spring Security는 필터 체인을 통해 클라이언트 요청을 처리하며 이 필터 체인은 여러 보안 필터로 구성되어 있습니다. 각 필터는 인증, 인가, 세션 관리, CORS 등 다양한 보안 기능을 수행합니다. Spring Security는 서블릿 필터를 기반으로 동작하며 HTTP 요청을 가로채고 보안 검사를 수행하여 요청이 적절한지 판단합니다. 또한 일반적인 서블릿 필터처럼 서블릿 컨테이너에 의해 관리됩니다. 

 

2. 서블릿 컨테이너와 스프링 빈

스프링 시큐리티의 필터들은 보안 설정이나 인증 서비스와 같은 다양한 스프링 빈에 의존하는데, 이를 위해 스프링 시큐리티에서는 서블릿 필터를 스프링 빈으로 등록하여 필요한 의존성을 주입받을 수 있도록 합니다. 그렇기 때문에 서플릿의 필터 기술을 스프링 시큐리티에서 사용할 수 있는 것입니다 하지만 한 가지 문제점이 있습니다. 이렇게 등록된 필터는 스프링 컨텍스트 내에서 필요한 빈들을 주입받을 수 있지만 서블릿 컨테이너가 해당 필터를 인식하지 못해 HTTP 요청을 처리할 수 없다는 것입니다.

 

즉, 스프링 빈으로만 등록된 필터는 서블릿 컨테이너의 필터 체인에 포함되지 않는 상태로써 필터로서의 역할을 할 수 없습니다.

 

스프링 빈으로 등록된 필터가 필터로서의 역할을 하려면 서블릿 컨테이너에 등록되어 요청을 필터 체인을 통해 처리하도록 연결해주는 객체가 필요합니다. 이 역할을 해주는 객체가 바로 DelegatingFilterProxy, FilterChainProxy입니다.

 

3. DelegatingFilterProxy, FilterChainProxy

 

스프링 시큐리티 내부에 있는 시큐리티 필터 체인이 필터로서의 역할을 하려면 연결 다리 역할을 해주는 객체가 필요하고 그 객체가 바로 DelegatingFilterProxy와 FilterChainProxy라고 했습니다. 위의 그림을 보면 DelegatingFilterProxy객체가 실체 서블릿  컨테이너의 필터체인의 등록되어 동작하면서 FilterChainProxy객체를 찾아서 역할을 위임하고 FilterChainProxy가 바로 securityFilterChain인 구조를 확인할 수 있습니다. 

 

DelegatingFilterProxy 

DelegatingFilterProxy는 서블릿 컨테이너의 필터체인의 등록되는 필터입니다. 이 필터는 HTTP 요청이 올 때 서블릿 컨테이너에 의해 호출되며, 요청을 스프링 컨텍스트에 등록된 실제 필터 빈에 위임(delegate) 합니다. 이 프록시 필터는 springSecurityFilterChain이라는 이름의 스프링 빈을 찾고, 그 빈을 호출하여 요청 처리를 진행하게 합니다.

  • 서블릿 필터의 구현체로서 서블릿 컨테이너에 등록되는 실제 서블릿 필터입니다.
  • 호출이 되면 "springSecurityFilterChain" 이름으로 등록된 빈을 찾아서 요청을 위임합니다.( 이때 찾은 빈의 실제 클래스는 FilterChianProxy입니다.)
  • DelegatingFilterProxy를 통해 서블릿 컨테이너는 springSecurityFilterChain이라는 이름의 스프링 빈에 포함된 모든 필터 체인을 필터처럼 사용할 수 있습니다.
  • 서블릿 컨테이너의 요청이 스프링 컨텍스트로 연결되고, 스프링 빈 필터가 서블릿 요청 처리 과정에 참여할 수 있게 됩니다.
DelegatingFilterProxy는 서블릿 메커니즘으로 서블릿의 필터로 등록될 수 있으며, 스프링에 등록된 빈을 가져와서 의존성을 주입할 수도 있습니다. 결론적으로 서블릿 컨테이너의 생명주기와 스프링의 ApplicationContext 사이를 연결하는 다리 역할을 하게 됩니다.

 

 

 

FilterChainProxy 

FilterChainProxy는 실제로 Spring Security의 보안 필터 체인을 관리하는 역할을 하며, 스프링 빈이자 서블릿 필터로 동작합니다. DelegatingFilterProxy가 받은 요청을 FilterChainProxy에 전달하면, FilterChainProxy는 스프링 컨텍스트에 등록된 여러 개의 보안 필터(인증, 인가, 세션 관리 등)를 순차적으로 적용해 요청을 처리합니다.

  • FilterChainProxy는 스프링 빈이면서, 서블릿 필터를 구현함.
  • DelegatingFilterProxy를 통해 받은 요청과 응답을 SecurityFilterChain에 전달하고 작업을 위임하는 역할을 한다.
  •  서블릿을 지원하는 시작점 역할을 하기 위함이다. 
  • FilterChainProxy에서 어떤 체인에게 작업을 위임할지도 결정할 수 있음

 

4. 정리

서블릿 필터는 원래 서블릿 기술이지만, 스프링 시큐리티는 이를 스프링의 빈 관리와 결합해 동작하게 합니다. 필터는 스프링 빈으로 등록되어 의존성을 주입받고, DelegatingFilterProxy와 FilterChainProxy 객체를 통한 연결로 인하여 서블릿 컨테이너의 관리하에 들어가 요청을 필터 체인에서 처리하게 됩니다.

 

서블릿 컨테이너는 DelegatingFilterProxy를 통해 Spring의 관리 영역으로 요청을 넘기고 Spring 컨테이너는 DI를 활용하여 필요한 보안 빈(SecurityFilterChain, AuthenticationManager 등)을 자동으로 제공하고 조립합니다. 이렇게 함으로써 서블릿 환경과 독립적으로 보안 설정을 선언적으로 구성할 수 있고, 애플리케이션의 유지보수성과 확장성을 높일 수 있습니다


이러한 구조 덕분에 스프링 시큐리티의 필터가 서블릿 컨테이너의 관리와 스프링의 의존성 주입 기능을 모두 활용할 수 있게 됩니다. 결과적으로 Spring Security는 서블릿 컨테이너와 스프링 컨테이너의 이점을 모두 활용하여 효과적인 보안 기능을 제공합니다.

 

이제 위에서 적었던 궁금증에 대한 답을 적어볼까요

 Q. 스프링 컨테이너에서 동작하는 spring security에 등록된 필터가 어떻게 http 요청을 가로채서 처리하는 필터의 역할을 수행할 수 있을까

 

    -  A. DelegatingFilterProxy가 실제 서블릿 필터체인에 등록되어서 동작하면서 호출이 되면 FilterChainProxy로 위임하고 FilterChainProxy이 내부로직을 통해 알맞은springSecurityFilterChain으로 역할을 위임합니다.

 

 

- Reference