필터 상속과 요청 전파

728x90

필터 상속과 요청 전파

SecurityFilterChain 의 필터

  • SecurityFilterChain 에 속한 각각의 필터를 이해하기 전에, 필터의 구조를 먼저 살펴보자.
  • 모든 필터는 공통된 부모 필터 클래스를 상속받아 구현되며, 이를 통해 중복 코드 방지 및 역할 분리가 가능하다.

필터의 상속

  • Spring Security 의 필터들은 계층적으로 구성되어 있으며, 공통적인 기능을 가진 부모 필터를 상속하여 구현된다.
  • 필터는 최상위 Filter 인터페이스를 기반으로 하며, 이를 확장하여 여러 필터가 존재한다.

SecurityFilterChain 에서의 필터 계층 구조

  • SecurityFilterChain 에서 필터들은 체인 형태로 연결되며, 각 필터가 특정 보안 로직을 수행한 후 다음 필터로 요청을 전달한다.

상속의 이점

  • 중복 코드 제거: 공통된 기능을 상위 클래스에서 정의하여 중복을 최소화할 수 있다.
  • 역할 분리: 부모 클래스는 공통적인 구조만 정의하고, 구체적인 기능은 하위 클래스에서 구현할 수 있다.
  • 유지보수 용이: 새로운 필터를 추가할 때 공통된 로직을 재사용할 수 있어 코드 변경이 용이하다.

예제: 로그인 필터의 계층 구조

Filter
   ├──GenericFilterBean (Spring Security 필터 기반)
        ├── AbstractAuthenticationProcessingFilter (기본 로그인 처리)
        │    ├── UsernamePasswordAuthenticationFilter (기본 폼 로그인)
        ├── LogoutFilter
        ├── OncePerRequestFilter
        │    ├── CsrfFilter

이처럼 공통 로직을 분리하고, 로그인 방식에 따라 다른 필터를 구현할 수 있다.

GenericFilterBean 과 OncePerRequestFilter

Spring Security 의 필터는 Servlet Filter 인터페이스를 기반으로 동작하며, 이를 확장한 두 가지 중요한 추상 클래스가 있다.

GenericFilterBean

  • GenericFilterBeanjavax.servlet.Filter 인터페이스를 구현한 추상 클래스이다.
  • Spring 환경과의 통합을 쉽게 하기 위해 사용되며, Spring Bean 으로 등록 가능하다.

GenericFilterBean 코드 구조

public abstract class GenericFilterBean implements Filter, BeanNameAware, EnvironmentAware,
  EnvironmentCapable, ServletContextAware, InitializingBean, DisposableBean {

}

서블릿 기반의 필터 인터페이스를 확장하여 Spring 환경에서 사용 가능하도록 설계 되었다.


OncePerRequestFilter

  • OncePerRequestFilterGenericFilterBean 을 확장한 추상 클래스이다.
  • 한 번의 요청 당 한 번만 실행되도록 설계된 필터이다.
  • 동일한 요청에서 여러 번 필터를 거칠 가능성이 있는 경우, 중복 실행을 방지할 수 있다.

OncePerRequestFilter 코드 구조

public abstract class OncePerRequestFilter extends GenericFilterBean {

  protected abstract void doFilterInternal(
    HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
    throws ServletException, IOException;
}

doFilterInternal() 메서드를 구현하여 한 번의 요청 당 한 번만 필터를 실행할 수 있도록 함.

OncePerRequestFilter 를 활용한 커스텀 필터 예제


@Component
public class CustomFilter extends OncePerRequestFilter {
  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
    throws ServletException, IOException {
    System.out.println("Custom Filter 실행됨: " + request.getRequestURI());
    filterChain.doFilter(request, response);
  }
}

이 필터는 한 번의 요청에 대해서만 실행되며, 이후 필터 체인으로 요청을 전달함.

필터 인터페이스와 주요 메서드

Filter 인터페이스는 필터의 기본적인 동작을 정의하는 3가지 메서드를 제공한다.

Filter 인터페이스 코드

public interface Filter {

  default void init(FilterConfig filterConfig) throws ServletException {
  }

  void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException;

  default void destroy() {
  }
}

주요 메서드

메서드 설명
init() 필터가 생성될 때 초기화 작업을 수행
doFilter() 요청을 처리하고, 다음 필터로 전달
destroy() 필터가 제거될 때 정리 작업 수행

FilterChain 에서 다음 필터 호출

  • 필터 체인 내에서 요청을 처리한 후 다음 필터를 실행해야 한다.
  • 이를 위해 FilterChain.doFilter(request, response); 를 호출한다.

LogoutFilterdoFilter() 예제

public class LogoutFilter extends GenericFilterBean {

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
    doFilter((HttpServletRequest) request, (HttpServletResponse) response, chain);
  }

  private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
    throws IOException, ServletException {

    // 로그아웃 처리 로직
    System.out.println("로그아웃 필터 실행됨");

    // 다음 필터 호출
    chain.doFilter(request, response);

    // 요청이 돌아와 다시 필터를 통과할 때 실행되는 로직
    System.out.println("로그아웃 필터 종료됨");
  }
}

위 코드에서 chain.doFilter(request, response); 를 호출하면 다음 필터가 실행된다.
이후 요청이 돌아올 때(응답 시점) 다시 실행될 수 있다.

728x90

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

DisableEncodeUrlFilter  (0) 2025.05.07
GenericFilterBean 과 OncePerRequestFilter  (1) 2025.05.06
SecurityContextHolder  (0) 2025.05.04
SecurityFilterChain 구조  (0) 2025.05.03
SecurityFilterChain 등록  (0) 2025.05.02