스프링 시큐리티가 서블릿 필터를 사용하는 방법

김태현·2023년 10월 9일

스프링과 서블릿 컨테이너의 관계

자바 기반 웹 애플리케이션이 TCP기반 http 프로토콜을 사용하면 서블릿 등 서블릿 컨테이너를 사용해야합니다. 스프링을 사용하면서 서블릿 컨테이너를 직접적으로 활용하진 않지만 내부적으로 서블릿과 필터를 사용합니다. 즉 스프링은 서블릿과 서블릿 필터를 더 쉽게 사용하고 구성할 수 있도록 도와주는 도구라고 생각합니다.

스프링은 서블릿과 필터를 활용하여 HTTP 요청과 응답을 처리하고 조작합니다. 스프링이 제공하는 추상화와 여러가지 기능을 통해 개발자는 서블릿과 필터의 구현에 대한 복잡성을 숨기고 더 높은 수준에서 비즈니스 로직을 작성할 수 있습니다.

결과적으로 스프링을 사용하더라도 서블릿 스펙은 웹 애플리케이션의 핵심 구성 요소로 남아있습니다.

필터의 역할

HTTP 요청 처리

필터는 클라이언트의 HTTP 요청이 서블릿에 도달하기 전에 가로채어 요청을 처리하는 역할을 합니다. 가로채어진 요청은 필터에서 정의한 작업을 수행한 후 해당 요청이 원래의 서블릿으로 전달되어 처리됩니다.

HTTP 응답 처리

비즈니스 로직을 타고 나가는 HTTP 응답을 가로채어 응답의 내용을 확인하거나 변경할 수 있습니다. 특히 HttpResponseWrapper 클래스를 extends 하여 요청을 Gzip으로 압축할 수 있습니다.

인증과 권한 부여

사용자의 인증 정보를 확인하거나 특정 리소스에 접근할 수 있는 권한을 확인하여 접근 제어를 수행할 수 있습니다. 해당 포스팅의 주제인 스프링 시큐리티와 같은 보안 관련 작업에 필터가 활용됩니다.

이 밖에도 서블릿 필터는 웹 애플리케이션에서 다양한 부분에서 중복으로 발생하는 작업을 처리하고 관리하는데 사용됩니다. (스프링 AOP와의 공통점)

스프링 시큐리티에서 필터를 사용하는 방법

스프링 시큐리티는 필터를 사용하여 웹 애플리케이션의 HTTP 요청 및 응답을 처리하고 보안 관련 작업을 수행합니다. 다음은 스프링 시큐리티에서 필터를 사용하는 방법입니다.

Filter 구성

스프링 시큐리티에서 필터는 필터 체인형태로 구성됩니다. 이 필터 체인은 웹 애플리케이션의 요청을 받아들이고 각각의 필터가 요청을 처리하며 보안 작업을 수행합니다. 필터 체인은 순차적으로 실행되며 각 필터는 다음 필터로 요청을 전달할 수도 있고 요청을 거부하거나 응답을 생성할 수도 있습니다.

필터의 종류

스프링 시큐리티는 다양한 종류의 필터를 제공하며 각 필터는 각각의 보안 작업을 처리합니다. 필터의 종류는 다음과 같습니다.

  • UsernamePasswordAuthenticationFilter: 사용자 로그인 처리 필터
  • BasicAuthenticationFilter: HTTP 기본 인증 처리 필터
  • SecurityContextPersistenceFilter: 보안 컨텍스트 저장 및 복원 필터
  • ExceptionTranslationFilter: 예외 처리 및 리다이렉션 필터
  • FilterSecurityInterceptor: 권한 및 인가 처리 필터 등

필터 체인 설정

필터 체인은 스프링 시큐리티 설정을 통해 구성됩니다. Java 설정이나 XML 설정을 사용하여 원하는 필터 체인을 정의하고 각 필터를 추가하거나 제거할 수 있습니다.

과거에는 WebSecurityConfigurerAdapter 클래스를 상속받아 configure(HttpSecurity http) 메서드를 오버라이딩 했지만 WebSecurityConfigurerAdapter가 Deprecated 되었습니다. 따라서 SecurityFilterChain을 Bean으로 등록해서 사용해야합니다.

// 과거, Deprecated 되었음
@Configuration 
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
 
   @Override 
   protected void configure(HttpSecurity http) throws Exception { 
     http.authorizeRequests() 
         .antMatchers("/home").permitAll()
         .antMatchers("/mypage").authenticated()
         .anyRequest().authenticated()
     ; 
   }
}

// SecurityFilterChain을 빈으로 등록해서 사용하는 방식
@Configuration 
@EnableWebSecurity
public class SecurityConfig {
 
   @Bean
   public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { 
        http.authorizeRequests() 
            .antMatchers("/home").permitAll()
            .antMatchers("/mypage").authenticated()
            .anyRequest().authenticated()
      return http.build();
   }
}
  • 주의할 점은 메서드 이름을 filterChain으로 사용해야합니다. 이름이 일치하지 않으면 스프링 시큐리티 설정이 적용되지 않습니다.

필터체인은 HTTP 요청 및 응답을 처리하기 위한 여러 필터(Filter)의 연속된 목록을 의미합니다. 이 필터 체인은 웹 애플리케이션에 들어오는 HTTP 요청을 받아들이고, 각각의 필터가 요청을 처리하며 응답을 생성합니다.

커스텀 필터

필요에 따라 커스텀 필터를 만들어 추가할 수도 있습니다. 커스텀 필터를 만들어 보안작업을 확장하거나 수정할 수 있습니다.

순서와 우선순위

필터 체인에서 각 필터의 순서와 우선순위를 주의깊게 관리해야합니다. 필터의 순서는 보안 작업의 흐름을 제어하기 때문에 순서에 신경써야합니다.

스프링 시큐리티 핵심 컴포넌트

DelegatingFilterProxy

  • DelegatingFilterProxy는 서블릿 컨테이너에 등록되는 스프링 빈입니다.
  • 서블릿 컨테이너는 이 필터를 실제로 인식하고 요청을 해당 필터로 라우팅합니다.
  • DelegatingFilterProxy는 스프링 애플리케이션 컨텍스트와 연결됩니다. 즉, 스프링 빈으로 등록되며 스프링의 IoC 컨테이너에서 관리됩니다.
  • DelegatingFilterProxy의 역할은 요청을 스프링 시큐리티의 FilterChainProxy에 위임하는 것입니다.

FilterChainProxy

  • FilterChainProxy는 스프링 시큐리티에서 모든 HTTP 요청을 받아들이고 보안 필터 체인을 관리하는 중요한 컴포넌트입니다.
  • FilterChainProxyDelegatingFilterProxy로부터 요청을 받아들이고, 해당 요청을 처리하기 위해 적절한 보안 필터 체인을 선택합니다.
  • 선택된 보안 필터 체인에 대한 요청을 라우팅하고, 각 필터가 요청을 처리하며 보안 작업을 수행합니다.
  • 보안 필터 체인은 스프링 시큐리티 설정에 따라 동적으로 결정되며, 다양한 보안 정책을 적용할 수 있도록 합니다.

SecurtyFilterChain

SecurityFilterChian은 스프링 시큐리티에서 사용되는 구성 요소 중 하나로 보안 필터들의 체인을 정의하고 관리하는데 사용됩니다. 이 필터체인은 웹 애플리케이션의 보안 관련 작업을 수행하기 위한 필터들의 순서와 구성을 정의합니다. 각 SecurityFilterChain은 특정 URL 패턴 또는 리소스에 대한 요청을 어떻게 처리할지 결정합니다.

일반적으로 웹 애플리케이션은 다양한 URL 패턴과 리소스를 가지며, 각각에 대해 다른 보안 요구사항이 적용되어야 합니다. 이때 SecurityFilterChain을 사용하여 다양한 요구사항을 처리하고 각 URL에 대해 다른 보안 필터 체인을 정의할 수 있습니다.

SecurityFilterChain`의 주요 역할은 다음과 같습니다:

  1. 보안 필터 체인 정의: SecurityFilterChain은 특정 URL 패턴 또는 리소스에 대한 보안 필터 체인을 정의합니다. 이 체인은 요청을 처리하고 보안 관련 작업을 수행합니다. 예를 들어, 인증, 인가, 세션 관리, CSRF 방어 등의 작업을 수행할 수 있습니다.
  2. 요청 라우팅: 클라이언트 요청이 들어왔을 때, SecurityFilterChain은 요청 URL과 일치하는 체인을 선택하고 해당 체인을 통해 요청을 라우팅합니다. 즉, 어떤 URL에 대한 요청이 어떤 보안 필터 체인을 통해 처리될지 결정합니다.
  3. 다중 SecurityFilterChain지원: 웹 애플리케이션에서 다양한 보안 요구사항을 처리해야 할 때, 여러 개의 SecurityFilterChain을 정의할 수 있습니다. 이를 통해 다양한 URL 및 리소스에 대한 보안 정책을 유연하게 관리할 수 있습니다.
  4. 구성 및 커스터마이징: 각 SecurityFilterChain은 다양한 보안 필터로 구성됩니다. 이 필터들은 스프링 시큐리티의 구성 설정에서 커스터마이징할 수 있으며, 애플리케이션의 특정 보안 요구사항에 맞게 조정할 수 있습니다.

스프링부트에서 스프링 시큐리티를 사용하는 방법

현재 스프링 시큐리티는 DelegatingFilterProxyFilterChainProxy를 직접 작성하지 않고, @EnableWebSecurity 어노테이션을 사용하여 간단하게 보안 설정을 구성할 수 있습니다.

@EnableWebSecurity 어노테이션은 스프링 시큐리티를 활성화 시키고 웹 보안 설정을 구성하는데 사용됩니다. 이 어노테이션을 사용하면 스프링 시큐리티를 웹 애플리케이션에 쉽게 통합하여 사용할 수 있습니다.

@EnableWebSecurity 어노테이션을 사용하는 클래스는 다음과 같은 기능을 제공합니다:

  1. 스프링 시큐리티 활성화: @EnableWebSecurity 어노테이션이 있는 클래스는 스프링 시큐리티를 활성화하고, 웹 보안을 구성하는 역할을 합니다.
  2. SecurityFilterChain 설정: SecurityFilterChain을 구성하고 관리하는 역할을 합니다. SecurityFilterChain은 웹 애플리케이션의 보안 필터 체인을 정의하고 관리하는 데 사용됩니다.
  3. 보안 규칙 정의: SecurityFilterChain filterChain(HttpSecurity http)를 빈으로 등록하여 필요한 보안 규칙을 설정할 수 있습니다. 예를 들어, URL 접근 권한, 로그인 페이지, 로그아웃 설정 등을 정의할 수 있습니다.

결과적으로 스프링부트에서 스프링 시큐리티를 사용하면 @EnableWebSecurity 어노테이션을 사용하여 웹 보안 설정을 구성하고, 보안 필터 체인을 정의할 수 있습니다. 이를 통해 웹 애플리케이션의 보안을 쉽게 통합하고 관리할 수 있습니다.

profile
안녕하세요. Java&Spring 기반 백엔드 개발자 김태현입니다.

0개의 댓글