본문 바로가기

Spring Boot/Security

필터 아키텍처 : 필터 순서와 우선순위

 - 서블릿 필터의 실행 순서가 왜 중요한가

 - Spring Boot에서 필터 순서를 지정하는법

 - @Order, Ordered 인터페이스, FilterRegistrationBean을 활용하는 방식

 - 필터 적용 조건을 설정하는 다양한 방법

 - 실무에서 필터 우선순위를 올바르게 설계하는 기준


필터 순서와 우선순위

서블릿 필터는 여러개가 동시에 등록될 수 있으며, 이 때 실행 순서에 따라 애플리케이션의 동작이 크게 달라진다

가령 인증(Authentication) 필터가 권한 부여(Authorization) 필터보다 뒤에서 실행된다면, 권한 검증을 수행할 수 없는 문제가 발생한다. 사실 말이 안되는거임

따라서 필터의 실행 순서를 올바르게 정의하는게 매우 중요하다

 

1. 필터 실행 순서의 중요성

보안 필터의 경우, 인증 필터 - > 권한 부여 필터 - > 로깅 필터 순으로 실행되는게 일반적이다

순서가 잘못될 경우,

  1. 인증되지 않은 사용자가 권한 검증 필터에 도달할 수 있다(인증과정을 거치지 않아서)
  2. 로깅이나 모니터링이 제대로 동작하지 않을 수 있다

필터 아키텍처, 인증 이후 인가가 이뤄저야함

 

 

 

2. 필터 순서 지정 방법

Spring Boot에서 필터의 실행순서를 지정하는 방법, 예

 

(1) @Order 애너테이션

package com.b1uffer.mysecurity.security.Filter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.springframework.core.annotation.Order;

import java.io.IOException;

/**
 * @Order 애너테이션
 * @Order는 해당 필터를 우선적으로 실행하게끔 한다
 * 괄호안의 숫자가 작을수록 우선순위가 높다, 즉 먼저 실행된다
 */
@Order(1)
public class FirstFilter implements Filter { // Filter import 클래스는 servlet이다
    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        System.out.println("First Filter 실행");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

 

 

 

(2) Ordered 인터페이스

package com.b1uffer.mysecurity.security.Filter;

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import org.springframework.core.Ordered;

import java.io.IOException;

/**
 * Ordered 인터페이스
 */
public class SecondFilter implements Filter, Ordered { // Ordered import는 core클래스
    @Override
    public int getOrder() {
        return 2; // 숫자가 클수록 나중에 실행된다
    }

    @Override
    public void doFilter(ServletRequest servletRequest,
                         ServletResponse servletResponse,
                         FilterChain filterChain) throws IOException, ServletException {
        System.out.println("Second Filter 실행");
        filterChain.doFilter(servletRequest, servletResponse);
    }
}

 

* Ordered 인터페이스를 구현하면 getOrder() 값으로 순서를 제어할 수 있으며, 제어해야한다

 

 

 

(3) FilterRegistrationBean

package com.b1uffer.mysecurity.security.config;

import com.b1uffer.mysecurity.security.Filter.FirstFilter;
import com.b1uffer.mysecurity.security.Filter.SecondFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfig {

    @Bean
    public FilterRegistrationBean<FirstFilter> firstFilterRegistration() {
        FilterRegistrationBean<FirstFilter> registration =
                new FilterRegistrationBean<>(new FirstFilter());

        registration.setOrder(1); // 먼저 실행하기
        return registration;
    }

    @Bean
    public FilterRegistrationBean<SecondFilter> secondFilterRegistration() {
        FilterRegistrationBean<SecondFilter> registration =
                new FilterRegistrationBean<>(new SecondFilter());

        registration.setOrder(2); // 두번째로 실행하기
        return registration;
    }
}

 

* setOrder() 메서드를 통해서 명시적으로 순서를 지정할 수 있다

* 숫자가 낮을수록 먼저 실행된다

 

 

3. 필터 적용 조건 설정

필터는 모든 요청에 적용할수도 있고, 특정 URL 패턴에만 적용할수도 있다

    @Bean
    public FilterRegistrationBean<FirstFilter> firstFilterRegistration() {
        FilterRegistrationBean<FirstFilter> registration =
                new FilterRegistrationBean<>(new FirstFilter());

        registration.setOrder(1); // 먼저 실행하기
        registration.addUrlPatterns("/api/*"); // 특정 경로에만 적용하기, 여기
        return registration;
    }

 

* addUrlPatterns() 메서드를 통해 특정 경로의 요청에 대해서만 필터가 적용된다

가령 addUrlPatterns("/api/*") 라고 URL패턴을 지정하면, api 이후의 경로들에 필터가 적용된다

 

* 모든 요청에 적용하려면 URL패턴을 지정하지 않으면 된다

 


  • 보안 관련 필터는 항상 Authentication(인증) - > Authorization(인가) - > 로깅 / 추적 순으로 배치하는게 좋다
  • 너무 많은 필터를 등록하면 요청 처리 속도가 느려질 수 있으므로, 꼭 필요한 필터만 사용하는게 좋다
  • FilterRegistrationBean을 이용하면 URL조건, 순서 등을 세밀하게 제어할 수 있어서 실무에서 가장 많이 사용된다고 한다
  • 외부 API 호출 로깅 필터나 트랜잭션 추적 필터는 가장 마지막에 배치하는것이 분석과 디버깅에 유리하다

정리

구분 설명
실행 순서 필터 실행 순서가 잘못되면 인증 / 인가 로직이 깨질 수 있음
@Order 애너테이션 애너테이션으로 순서를 지정한다 (숫자가 작을수록 먼저 실행됨)
Ordered 인터페이스 getOrder() 구현으로 순서를 제어한다
FilterRegistrationBean 필터 등록 및 순서 / 조건을 명시적으로 설정 가능함
URL 조건 addUrlPatterns()으로 특정 경로에만 적용할 수 있음