필터 체인 등록

dasd412·2022년 3월 15일
0

JWT

목록 보기
4/9

커스텀 필터 클래스

커스텀 필터 클래스를 만들려면 Filter 인터페이스의 doFilter()를 재정의해야 한다.

filterChain.doFilter(servletRequest,servletResponse); 는 필터체인에 등록되있는 다음 필터를 호출하는 코드이다.

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

public class MyFilter1 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter 1");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}
public class MyFilter2 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        System.out.println("filter 2");
        filterChain.doFilter(servletRequest,servletResponse);
    }
}

필터 체인 등록하기

커스텀 필터를 필터체인에 등록하는 방법 중 하나는 @Configuration 으로 등록한 필터 설정용 클래스에 빈으로 등록하는 것이다.

FilterRegistrationBean<T> 를 빈으로 등록하면 되는데, 제네릭 T에 커스텀 필터를 넣으면 된다.

커스텀 필터는 기본적으로 시큐리티 필터보다 후순위이다.

WebSecurityConfigurerAdapter 상속체의 configure(HttpSecurity http) 메서드에서 addFilterBefore()등을 이용하면 시큐리티 필터보다 순위를 높게 가질 수 있다.

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<MyFilter1> filter1(){
        FilterRegistrationBean<MyFilter1>bean=new FilterRegistrationBean<>(new MyFilter1());
        bean.addUrlPatterns("/*");//모든 요청에 대해 필터를 거쳐라.
        bean.setOrder(0);//필터의 우선순위. 0에 가까울 수록 높음
        return bean;
    }

    @Bean
    public FilterRegistrationBean<MyFilter2> filter2(){
        FilterRegistrationBean<MyFilter2>bean=new FilterRegistrationBean<>(new MyFilter2());
        bean.addUrlPatterns("/*");//모든 요청에 대해 필터를 거쳐라.
        bean.setOrder(1);//필터의 우선순위. 0에 가까울 수록 높음
        return bean;
    }
}

시큐리티 필터보다 우선 순위 높게 변경하기

먼저 다음과 같이 커스텀 필터를 만든다.

public class MyFilter3 implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest req=(HttpServletRequest)servletRequest;
        HttpServletResponse res=(HttpServletResponse)servletResponse;

        if (req.getMethod().equals("POST")){

            String headerAuth=req.getHeader("Authorization");
         
            //토큰 : cors 이걸 만들어서 줘야 한다.
            //id,pw가 정상적으로 들어와서 로그인이 완료되면 토큰을 만들어주고 그걸로 응답을 해준다.
            //요청할 때마다 header의 Authroization에 value 값으로 토큰을 가지고 온다.
            //그 토큰이 넘어오면 이 토큰이 내가 만든 토큰이 맞는지만 검증만 하면 된다.
            if (headerAuth.equals("cors")){
                filterChain.doFilter(servletRequest,servletResponse);
            }
            else{
                System.out.println("filter 3");
                PrintWriter outPrintWriter=res.getWriter();
                outPrintWriter.println("인증 안됨.");
            }
        }
    }
}

위 커스텀 필터는 request의 HTTP 메서드가 POST 요청이면 가로채서 헤더 부분을 파악한다. 만약 헤더에 Authorization 이라는 키의 value(→headerAuth)를 얻어낸다.

이 때 value가 서버에 있는 토큰 값과 같다면, 인증을 해준 사용자가 맞기 때문에 다음 필터체인으로 넘어간다.

그렇지 않으면 다른 사용자이므로 인증이 필요하다. 따라서 다음 필터로 넘어가지 못하게 하였다.

이 커스텀 필터를 스프링 시큐리티가 제공하는 필터보다 우선 순위를 높게 하려면 설정용 클래스에서 addFilterBefore()를 이용하면 된다.

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
								....
                .and()
                .addFilterBefore(new MyFilter3(), SecurityContextHolderAwareRequestFilter.class)
								....

    }
}

아래와 같이 헤더에 Authorization : cors 라 적고 포스트 요청을 하게 되면 커스텀 필터가 먼저 걸러내는 것을 확인할 수 있다.

profile
시스템 아키텍쳐 설계에 관심이 많은 백엔드 개발자입니다. (Go/Python/MSA/graphql/Spring)

0개의 댓글