상세 컨텐츠

본문 제목

[Spring] Filter Example

Spring/Spring Security

by Chan.94 2024. 8. 14. 11:25

본문

반응형

Filter

필터, 인터셉터, AOP를 사용하는 가장 큰 이유는 중복된 코드를 줄여 관리가 용이하게 하기 위함이다.

코드의 중복을 줄이고 관심사를 분리하여 개발자는 비지니스 로직에 집중할 수 있다.

(공통 영역과 비지니스 영역 분리)

 

필터(Filter)는 Dispatcher Servlet에 요청이 전달되기 전/후에 url 패턴에 맞는 모든 요청에 대해 부가작업을 처리할 수 있는 기능을 제공한다.

스프링 컨테이너가 아닌 톰캣과 같은 웹 컨테이너에 의해 관리가 되는 것이고 디스패처 서블릿 전/후에 처리하는 것이다.

(스프링 빈으로 등록은 된다)

 

필터 사용 예시

  • 보안 및 인증/인가 관련 작업
    필터는 인터셉터보다 앞단에서 동작하기 때문에 보안 검사(XSS 방어 등)를 하여 올바른 요청이 아닐 경우 차단할 수 있다. Spring 컨테이너까지 요청이 전달되지 못하고 차단하기기 때문에 안전성을 더욱 높일 수 있다.
    대표적으로 필터(Filter)를 인증과 인가에 사용하는 도구로는 Spring Security가 있다.
  • 모든 요청에 대한 로깅 또는 검사

  • 이미지/데이터 압축 및 문자열 인코딩

Spring Security 개념 및 Architecture

 

Spring Security 개념 및 Architecture

Spring SecuritySpring 기반의 애플리케이션의 보안(인증과 권한, 인가 등)을 담당하는 스프링 하위 프레임워크이다.다시 말해서 인증(Authentication, 누구인지)과 인가(Authorization, 어떤 것을 할 수 있는지

fvor001.tistory.com

 


필터 체이닝

FilterChain은 서블릿 컨테이너가 관리하는 필터들의 연결고리로, 클라이언트의 요청이 서블릿에 도달하기 전에 여러 필터를 순차적으로 거치게 하는 메커니즘이다.

필터 등록 및 체이닝 설정

Spring Boot에서는 FilterRegistrationBean을 사용하여 필터를 등록하고, 필터의 순서를 정의할 수 있다.

FilterRegistrationBean을 사용하면 필터의 순서를 setOrder 메서드를 통해서 명시적으로 지정할 수 있다.

 


Filter 인터페이스

필터를 추가하기 위해서는 javax.servlet의 Filter 인터페이스를 구현해야 하며 이는 다음의 3가지 메서드를 가지고 있다.

public interface Filter {

    public default void init(FilterConfig filterConfig) throws ServletException {}

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

    public default void destroy() {}
}
  • init
    필터 객체를 초기화하고 서비스에 추가하기 위한 메서드이다. 웹 컨테이너가 1회 init 메서드를 호출하여 필터 객체를 초기화하면 이후의 요청들은 doFilter를 통해 처리된다.

  • doFilter
    url-pattern에 맞는 모든 HTTP 요청이 서블릿으로 전달되기 전에 웹 컨테이너에 의해 실행되는 메서드이다.
    doFilter의 파라미터로는 FilterChain이 있는데, FilterChain의 doFilter 통해 다음 대상으로 요청을 전달하게 된다. doFilter() 전/후에 우리가 필요한 처리 과정을 넣어줌으로써 원하는 처리를 진행할 수 있다.
  • destroy
    필터 객체를 서비스에서 제거하고 사용하는 자원을 반환하기 위한 메소드이다.

FirstFilter.java

@Slf4j
public class FirstFilter implements Filter{

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		log.info("==========First Filter START==========");
		filterChain.doFilter(servletRequest, servletResponse);
		log.info("==========First Filter END==========");
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		log.info("FirstFilter init");
	}

	@Override
	public void destroy() {
		log.info("FirstFilter destroy");
	}
}

 

SecondFilter.java

@Slf4j
public class SecondFilter implements Filter {

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
		log.info("==========Second Filter START==========");
		filterChain.doFilter(servletRequest, servletResponse);
		log.info("==========Second Filter END==========");
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		log.info("SecondFilter init");
	}

	@Override
	public void destroy() {
		log.info("SecondFilter destroy");
	}
}

 

 

FilterConfiguration.java

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

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

 

setOrder로 Filter 순서를 지정한다.

 

동작확인

(1) Init

 

(2) Client Request시

필터 체이닝에 의해 순차적으로 실행되고 요청이 끝난 후 역순으로 종료되는 것을 확인할 수 있다.

 

(3) 서버 종료 시

 

반응형

관련글 더보기

댓글 영역

>