[Spring Security] 6. 필터 상속과 요청 전파

조성우·2024년 8월 9일

Spring Security

목록 보기
5/16
post-thumbnail

SecurityFilterChain에 속한 각각의 필터를 알아보기 전에, 필터의 전반적인 구조를 살펴보자.


필터의 상속

각 필터의 조상은 모두 동일하다. 필터의 기반이 되는 필터 클래스를 만들어두고 해당 클래스를 상속 받아 각 특성에 맞게 구현되어 있다.

SecurityFilterChain에서 구조는 아래와 같다.

상속의 이점

중복되는 코드를 줄이고 각각의 구현부가 자신이 가지는 책임에 대해서만 작업을 수행하면 된다.

상단의 필터 클래스는 필터의 구조적인 역할만, 필터를 상속 받은 구현부는 구현부의 역할만 수행한다.

예를 들어 로그인 필터의 경우, 로그인의 종류가 아주 많기 때문에 기본적인 로그인 틀을 구현 1로 구현하고, 세부적인 로그인 방식을 구현 2로 구현하여 등록한다.

※ 예시로 몇 가지의 필터들을 살펴보자!

  1. UsernamePasswordAuthenticationFilter

  1. LogoutFilter

  1. CsrfFilter


GenericFilterBean과 OncePerRequestFilter

서블릿 기반의 Filter 인터페이스 바로 아래에 내려가면 GenericFilterBeanOncePerRequestFilter 두가지 추상 클래스가 존재하며, 모든 필터는 두 추상 클래스를 기반으로 구현되어 있다.

GenericFilterBean

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

}

OncePerReqeustFilter

public abstract class OncePerRequestFilter extends GenericFilterBean {

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

GenericFilterBean 추상 클래스는 자바 서블릿 필터 기반으로 구현되어 있으며 자바 서블릿 영역에서 스프링 영역에 접근할 수 있도록 작성되어 있다.

OncePerRequestFilter는 GenericFilterBean을 기반으로 작성된 추상 클래스로, 클라이언트의 한 번 요청에 대해 내부적으로 동일한 서블릿 필터를 여러번 거칠 경우 한 번만 반응하도록 설계되어 있다. (한 번에 요청에 대해 한 번만 반응)


필터의 형식

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() {
    }
}

인터페이스로 3가지 메소드를 정의해 두었다.

  • init()
    서블릿 컨테이너 실행시 필터를 생성하고 초기화할 때 사용하는 메소드

  • doFilter()
    요청에 대한 작업 수행 및 다음 필터를 호출하는 메소드

  • destory()
    서블릿 컨테이너 종료시 초기화하는 메소드


filterChain에서 다음 필터 호출

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("before");

		//다음 필터 호출
		chain.doFilter(request, response);
		
		//요청이 돌아서 다시 현재 필터를 통과할 때 처리할 로직
		//System.out.println("after");
	}
    
}

※ GenericFilterBean과 OncePerRequestFilter의 로직 수행 메소드

  • GenericFilterBean : doFilter()
  • OncePerRequestFilter : doFilterInternal()

0개의 댓글