티스토리 뷰

Filter

  • 필터는 외부 요청을 가장 먼저 검증하는 곳이다. 커스텀 필터를 만들어서 테스트해보자.

Filter 생성

@Slf4j
public class MyFilter1 implements Filter {
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		log.info("Filter 1");
		chain.doFilter(request, response);
	}
}
  • Filter 인터페이스를 상속받아서 구현해주면 된다. 이때 메소드는 init(), destroy(), doFilter()가 있다.
  • Parameter로 웹 요청, 응답과 필터 체인이 있는것을 확인할 수 있다.
  • chain.doFilter()를 통해 현재 필터에서 로직을 수행하고 다음 필터로 넘기게 된다.

이러한 필터를 3개 정도 생성하고 적용시키 위해서는 FilterConfig 클래스를 만들어서 Filter들을 Bean으로 생성해서 등록시켜줘야 한다. 그럼 스프링 컨테이너가 DI 해준다.

 

FilterConfig

@Configuration
public class FilterConfig {
	/*
    직접 만든 Filter 들은	Spring Security Filter 이후에 적용된다.
	더 앞에서 적용하고 싶다면 Security Config 에서 addFilterBefore()로 적용하면 된다.
	-> http.addFilterBefore(new MyFilter3(), BasicAuthenticationFilter.class);
	이런 식으로 Spring Security에 넣으면 된다.
	 */
	@Bean
	public FilterRegistrationBean<MyFilter1> filter1() {
		FilterRegistrationBean<MyFilter1> bean = new FilterRegistrationBean<>(new MyFilter1());
		bean.addUrlPatterns("/*");	// 해당 url에 맞는 요청에 Filter가 적용된다.
		bean.setOrder(0);			// 숫자가 작은 순서대로 적용된다.
		return bean;
	}

	@Bean
	public FilterRegistrationBean<MyFilter2> filter2() {
		FilterRegistrationBean<MyFilter2> bean = new FilterRegistrationBean<>(new MyFilter2());
		bean.addUrlPatterns("/*");
		bean.setOrder(1);
		return bean;
	}

	@Bean
	public FilterRegistrationBean<MyFilter3> filter3() {
		FilterRegistrationBean<MyFilter3> bean = new FilterRegistrationBean<>(new MyFilter3());
		bean.addUrlPatterns("/*");
		bean.setOrder(2);
		return bean;
	}
}
  • 이때 어느 URL에 필터를 적용할지 + 필터의 순서를 적어주면 된다. 순서는 수가 빠른순서이다.

테스트

요청을 받는 컨트롤러

@RestController
public class HomeController {
	@PostMapping("/token")
	public String postToken() {
		return "<h1>good<h1>";
	}
}

시큐리티 필터 앞에 필터 로그 출력용 추가
POST 요청

위와 같이 스프링 시큐리티 필터가 먼저 적용되고 이후 커스텀 필터 1, 2, 3 이 수행된걸 확인할 수 있다.

 

이제 이러한 구조하에서 JWT을 검증하는 로직을 넣어보자.

JWT 임시 검증 로직

임시 Token 검증 로직

@Slf4j
public class MyFilter4 implements Filter {
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		log.info("Security Filter Start");

		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;

		/*
		토큰: token 이 필요하다. id/pw 가 정상적으로 들어와서 로그인이 완료되면 토큰을 만들고 반환해준다.
		클라이언트는 요청할 때 마다 header 에 Authorization - value 쌍으로 토큰을 넣으면 된다.
		이때 토큰이 서버가 갖고있는 토큰인지 검증만 하면 된다.
		 */

		if (req.getMethod().equals(HttpMethod.POST.name())) {
			log.info("POST 요청");
			String headerAuth = req.getHeader("Authorization");
			if (headerAuth.equals("token")) {
				log.info("Filter 4");
				log.info(headerAuth);
				chain.doFilter(req, res);
			} else {
				log.error("인증안됨");
			}
		}
	}
}
  • 인가 코드가 확인이 되면 Filter Chain을 이어서 진행하고, 그렇지 않다면 "인증안됨"을 출력하고 요청을 종료시켜버린다.

테스트

요청 시 Authorizaton에 "token2"를 넣어서 보내는 경우 (잘못된 토큰)

  • 시큐리티 필터에서 걸러진 것을 확인할 수 있다.
요청 시 Authorization에 "token"을 넣어서 보내는 경우 (올바른 토큰)

  • 정상적으로 필터에서 처리되어 모든 필터가 순차적으로 진행된 것을 확인할 수 있다.

 

이러한 플로우로 최초 로그인 요청 시 ID/PW 검증 후 Token을 발급해주고, 이후 다른 요청들에 대해 Token을 확인하고 CONFIRM / REJECT 여부를 결정해주면 되겠다.

 

다음 포스팅에서 이어서 정리해겠다.

반응형
Comments
반응형
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday