본문 바로가기

Spring Boot/Security

커스텀 필터 구현 : 필터체인에 커스텀 필터 추가하기

 - Spring Security의 필터 체인 구조 이해하기

 - 커스텀 필터를 필터 체인에 추가하는 방법

 - 특정 위치에 커스텀 필터를 삽입하는 방법

 - 기존 필터 앞 / 뒤에 배치하여 실행 순서를 제어하는 방법 알기

 - URL 패턴 기반 필터 적용 대상을 제한하는 두가지 방식(단일 체인 vs 다중 체인) 비교해서 알기


필터 체인에 커스텀 필터 추가

1. 특정 위치에 필터 추가하기

Security에서는 필터 체인에 커스텀 필터를 원하는 위치에 추가할 수 있다

일반적으로 SecurityFilterChain을 구성할 때

addFilterBefore, addFilterAfter, addFilterAt 메서드를 사용할 수 있다

   @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(new CustomOncePerRequestFilter(), 
                    UsernamePasswordAuthenticationFilter.class)
                .authorizeHttpRequests(auth -> auth

 

addFilterBefore(new CustomOncePerRequestFilter(), UsernamePassword...); 는

UsernamePasswordAuthenticationFilter 실행 전에 CustomOncePerRequestFilter를 실행하게끔 하는 메서드이다

 

 

2. 기존 필터 앞 / 뒤 배치

  • addFilterBefore : 지정된 필터 앞에 커스텀 필터를 추가한다
  • addFilterAfter : 지정된 필터 뒤에 커스텀 필터를 추가한다
  • addFilterAt : 지정된 필터와 같은 위치에 추가한다
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(new CustomOncePerRequestFilter(), 
                    UsernamePasswordAuthenticationFilter.class)
                .addFilterAfter(new CustomGenericFilter(), CsrfFilter.class)
                .addFilterAt(new CustomOncePerRequestFilter(), BasicAuthenticationFilter.class)

 

이런 형태로 작성하면 커스텀 필터의 실행 순서를 원하는대로 조정할 수 있다고 함

 


URL 패턴 기반 필터 적용

커스텀 필터를 모든 요청에 대해 적용하는 것이 아니라, 특정 URL 패턴에만 적용할수도 있다

이 때, 두가지 접근 방식이 있음

 

1. 방법 1 : 단일 체인 + 내부 분기

  • 하나의 SecurityFilterChain 만 존재한다
  • 모든 요청이 같은 필터 체인을 거친다
  • 필터 내부에서 request.getRequestURI()를 검사하여 조건 분기를 한다
 public class CustomOncePerRequestFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain filterChain) throws ServletException, IOException {   
                                    
        // 필터체인 이전에 실행할 로직
        
        String path = request.getRequestURI();
        if(path.startsWith("/api/secure/")) {
            // 특정 URI에만 실행할 로직 구현
        }
        
        // 필터 체인 진행
        filterChain.doFilter(request, response);

 

장점 : 구현이 단순함

단점 : 모든 요청이 필터를 거치기 때문에 불필요한 요청에 대해서도 실행된다

 

 

 

2. 방법 2 : 다중 SecurityFilterChain 구성하기

URL 패턴별로 별도의 SecurityFilterChain을 정의한다

/api/secure/** 요청은 해당 체인만 타고, 다른 요청은 별도 체인이 처리하게끔 구성

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http    .securityMatcher("/api/secure/**") // 해당 체인이 이 URL만으로 처리된다
                .addFilterBefore(new CustomOncePerRequestFilter(), 
                    UsernamePasswordAuthenticationFilter.class)
                .addFilterAfter(new CustomGenericFilter(), CsrfFilter.class)
                .addFilterAt(new CustomOncePerRequestFilter(), BasicAuthenticationFilter.class)

 

장점 : 불필요한 요청은 아예 제외되므로 성능 및 안정성이 올라간다

단점 : 체인이 여러개 생기므로 관리가 복잡해질 수 있다

 

 

 

3. 비교

구분 단일 체인 + 내부 분기 다중 체인
실행 방식 모든 요청이 필터를 거치고 내부에서 URL을 검사함 URL 패턴 매칭 후 해당 체인만 실행함
장점 단순 구현, 빠른 적용 불필요한 요청 제외, 성능 올라감
단점 모든 요청 실행 - > 오버헤드 발생 가능성 필터 체인 관리 복잡도가 올라감
추천 상황 간단 조건, 테스트 / 프로토타입 운영 환경, URL별 보안 정책 구분 필요시

 


  • 커스텀 필터는 보통 인증 / 인가 전에 실행되어야 하므로
    일반적으로 UsernamePasswordAuthenticationFilter 앞에 배치하는 경우가 많다
  • 여러개의 필터를 추가할 경우, 실행 순서를 명확하게 정의해야 디버깅이 쉽다
  • 운영 환경에서는 다중 체인 방식으로 URL 구간별 보안 정책을 분리하는 것이 더 권장된다고 함
  • 단순 실습, 보조 로직은 단일 체인 내부 분기 방식이 더 간편하다