Java_Spring Security

Minki CHO·2023년 1월 16일
0

CodeStates

목록 보기
17/43

Filter와 FilterChain 구현

Filter

서블릿 필터Servlet Filter
:서블릿 기반 애플리케이션의 엔드포인트에 요청이 도달하기 전에 중간에서 요청을 가로챈 후 어떤 처리르 할 수 있도록 해주는 Java 컴포넌트


:서블릿 기반 애플리케이션에서의 Filter 위치
:위 그림처럼 클라이언트가 서버 측 애플리케이션으로 요청을 전송하면 제일 먼저 Servlet Filter를 거치게 됨. 그리고 Filter에서의 처리가 모두 완료되면 DispatcherServlet에서 클라이언트의 요청을 핸들러 메서드에 매핑하기 위한 다음 작업을 진행함

Filter Chain

:여러개의 Filter가 체인을 형성하고 있는 Filter 묶음을 의미함

Filter와 Filter Chain 특성

1)Servlet FilerChain은 요청 URL path를 기반으로 HttpServletRequest를 처리함
따라서 클라이언트가 서버 측 애플리케이션에 요청을 전송하면 서블릿 컨테이너는 요청 URL의 경로를 기반으로 어떤 Filter와 어떤 Servlet을 매핑할지 결정함

2)Filter는 Filter Chain 안에서 순서를 지정할 수 있으며 지정한 순서에 따라서 동작하게 할 수 있음

3)Filter Chain에서 Filter의 순서는 매우 중요
Spring Boot에서 여러개의 Filter를 등록하고 순서를 지정하기 위해서는 다음 두 가지 방법 적용 가능
a. Spring Bean으로 등록되는 Filter에 @Order 애너테이션을 추가하거나 Order 인터페이스를 구현해서 Filter의 순서 지정 가능
b. FilterRegistrationBean을 이용해 Filter 순서를 명시적으로 지정 가능

Filter 인터페이스

public class FirstFilter implements Filter {
     // 1) 초기화 작업
     public void init(FilterConfig filterConfig) throws ServletException {
        
     }
     
     // 2)
     public void doFilter(ServletRequest request,
                          ServletResponse response,
                          FilterChain chain)
                          throws IOException, ServletException {
        // 2-1) 이 곳에서 request(ServletRequest)를 이용해 다음 Filter로 넘어가기 전처리 작업을 수행한다.

        // 2-2)
        chain.doFilter(request, response);

        // 2-3) 이 곳에서 response(ServletResponse)를 이용해 response에 대한 후처리 작업을 할 수 있다.
     }
     
     // 3)
     public void destroy() {
        // 5) Filter가 사용한 자원을 반납하는 처리
     }
  }

:Servlet Filter 인터페이스를 구현한 구현 클래스의 기본 구조

1) public void init(FilterConfig filterConfig) throws ServletException {...}
:생성한 Filter에 대한 초기화 작업을 진행할 수 있음

2) public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException{...}
:doFilter() 메서드에서 해당 Filter가 처리하는 실질적 로직 구현

2-1)
:request를 이용해 2-2) chain.doFilter(request, response)가 호출되기 전에 할 수 있는 전처리 작업에 대한 코드를 구현

2-3)
:response를 이용해 2-2) chain.doFilter(request, response) 호출된 후에 할 수 있는 후처리 작업에 대한 코드를 구현

3) public void destroy() {...}
:Filter가 컨테이너에서 종료될 때 호출됨
:주로 Filter가 사용한 자원을 반납하는 처리 등의 로직을 작성하고자 할 때 사용

Filter 실습 예제

1 첫 번째 Filter 구현

import javax.servlet.*;
import java.io.IOException;

public class FirstFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        System.out.println("FirstFilter 생성됨");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("========First 필터 시작========");
        chain.doFilter(request, response);
        System.out.println("========First 필터 종료========");
    }

    @Override
    public void destroy() {
        System.out.println("FirstFilter Destory");
        Filter.super.destroy();
    }
}

2 FirstFilter를 적용하기 위한 FilterConfiguration 구성

import book.study.security.FirstFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class FilterConfiguration {

    @Bean
    public FilterRegistrationBean<FirstFilter> firstFilterRegister()  {
        FilterRegistrationBean<FirstFilter> registrationBean = new FilterRegistrationBean<>(new FirstFilter());
        return registrationBean;
    }
}

:Spring Boot에서 Servlet Filter는 위 코드와 같이 FilterRegistrationBean의 생성자로 Filter 인터페이스의 구현 객체를 넘겨주는 형태로 등록할 수 있음<노이해중>

3 애플리케이션 실행

애플리케이션 실행 시 가장 먼저 init() 메서드 실행되며 아래 로그 출력됨

FirstFilter 생성됨

다음으로 만든 Controller가 있다면 해당 컨트롤러의 핸들러 메서드로 요청을 보내기

doFilter -> controller 동작 -> destroy 메서드 형태로 Filter 동작하며 아래와 유사한 로그 출력

========First 필터 시작========
Hello
========First 필터 종료========

4 두 번째 Filter 구현

import javax.servlet.*;
import java.io.IOException;

public class SecondFilter implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        Filter.super.init(filterConfig);
        System.out.println("SecondFilter가 생성되었습니다.");
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println("==========Second 필터 시작==========");
        chain.doFilter(request, response);
        System.out.println("==========Second 필터 종료==========");
    }

    @Override
    public void destroy() {
        System.out.println("SecondFilter가 사라집니다.");
        Filter.super.destroy();
    }
}

:두 번째 Filter 작성

5 FilterConfiguration에 두 번째 Filter 등록

import book.study.security.FirstFilter;
import book.study.security.SecondFilter;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Config {

    @Bean
    public FilterRegistrationBean<FirstFilter> firstFilterRegister()  {
        FilterRegistrationBean<FirstFilter> registrationBean = new FilterRegistrationBean<>(new FirstFilter());
        registrationBean.setOrder(1); // 1)
        return registrationBean;
    }

    @Bean
    public FilterRegistrationBean<SecondFilter> secondFilterRegister()  {
        FilterRegistrationBean<SecondFilter> registrationBean = new FilterRegistrationBean<>(new SecondFilter());
        registrationBean.setOrder(2); // 2)
        return registrationBean;
    }

}

:두 번째 Filter인 SecondFilter를 Spring Bean으로 등록

1) registrationBean.setOrder(1) 2) registrationBean.setOrder(2)
:두 개의 Filter가 지정된 순서로 실행되도록 registratioinBean.setOrder() 메서드로 순서 지정할 수 있음
:파라미터로 지정한 숫자가 적은 숫자일수록 먼저 실행됨

애플리케이션 재실행 후 Controller의 핸들러 메서드에 request를 전송하면 아래 같은 결과 출력

========First 필터 시작========
==========Second 필터 시작==========
Hello
==========Second 필터 종료==========
========First 필터 종료========

"Filter는 나머지 Filter와 Servlet에 영향을 주기 때문에 Filter의 실행 순서가 중요함"

핵심
-Spring Boot에서는 FilterRegistrationBean을 이용해 Filter를 등록할 수 있음
-Spring Boot에서 등록하는 Filter는 아래 방법으로 실행 순서 지정 가능
a. Spring Bean으로 등록되는 Filter에 @Order 애너테이션 추가 및 Order 인터페이스를 구현
b. FilterRegistrationBean의 setOrder() 메서드를 이용해 순서 지정 가능

profile
Developer

0개의 댓글