- 지난번까지 해서 Security 설정을 마쳤다. 이제 filter를 생성하고 등록해보자!
MyFilter.java 생성
- filter 패키지를 생성하여 클래스를 생성해주자
package com.pem.jwt.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter1 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("필터1");
// 여기서 response를 이용해 응답을 보내버리면 프로세스가 끝나버리기 때문에
// 프로세스를 진행하기 위해 다시 필터에 요청과 응답을 넘겨줘야 한다.
chain.doFilter(request, response);
}
}
SecurityConfig.java 수정
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
// 아래 한 줄만 추가 됨
http.addFilterBefore(new MyFilter1(), BasicAuthenticationFilter.class);
return http
.csrf().disable()
- 그런데 filterChain의 리턴 타입은 SecurityFilterChain으로 Filter와 리턴 타입이 달라 에러가 발생한다. 이를 위해 addFilterBefore 또는 addFilterAfter를 이용하여 BasicAuthenticationFilter가 등록되기 전에 MyFilter1를 먼저 등록해주자!
그리고 localhost:8080/home으로 접근한 뒤, 콘솔을 확인해보면 필터가 등록되어 있는 것을 확인할 수 있다.
- 그런데 FilterChain에 필터를 등록하는 방법 뿐만 아니라 따로 걸어주는 방법도 해보자.
SecurityConfig.java 수정
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http
.csrf().disable()
FilterConfig 생성
package com.pem.jwt.config;
import com.pem.jwt.filter.MyFilter1;
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);
return bean;
}
}
- FilterRegistrationBean을 이용해 MyFilter1을 빈으로 등록하고, 필터를 적용할 url을 설정해주자
- 그리고 다시 home으로 접근하면 필터가 적용되어 있는 것을 확인할 수 있다.
- 필터를 추가로 등록해보자
MyFilter2 생성
package com.pem.jwt.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter2 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("필터2");
// 여기서 response를 이용해 응답을 보내버리면 프로세스가 끝나버리기 때문에
// 프로세스를 진행하기 위해 다시 필터에 요청과 응답을 넘겨줘야 한다.
chain.doFilter(request, response);
}
}
- MyFilter1을 복사하여 이름을 변경하고, 코드도 숫자만 변경해주자
FilterConfig 수정
@Configuration
public class FilterConfig {
@Bean
public FilterRegistrationBean<MyFilter1> filter1() {
FilterRegistrationBean<MyFilter1> bean = new FilterRegistrationBean<>(new MyFilter1());
bean.addUrlPatterns("/*");
// 필터의 우선순위를 정하는 메소드
// 숫자가 낮을 수록 우선순위는 높다.
bean.setOrder(0);
return bean;
}
@Bean
public FilterRegistrationBean<MyFilter2> filter2() {
FilterRegistrationBean<MyFilter2> bean = new FilterRegistrationBean<>(new MyFilter2());
bean.addUrlPatterns("/*");
// 필터의 우선순위를 정하는 메소드
// 숫자가 낮을 수록 우선순위는 높다.
bean.setOrder(1);
return bean;
}
}
- FilterConfig에 filter2를 추가로 등록해줬다. 그리고 다시 home으로 등록해주면 필터가 정상적으로 등록되어 있는 것을 확인할 수 있다.
- 그럼 SecurityFilterChain이 먼저 등록이 될까? 내가 생성한 필터가 먼저 등록이 될까? 확인해보자
MyFilter3 생성
package com.pem.jwt.filter;
import javax.servlet.*;
import java.io.IOException;
public class MyFilter3 implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
System.out.println("필터3");
// 여기서 response를 이용해 응답을 보내버리면 프로세스가 끝나버리기 때문에
// 프로세스를 진행하기 위해 다시 필터에 요청과 응답을 넘겨줘야 한다.
chain.doFilter(request, response);
}
}
SecurityConfig.java 수정
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilterBefore(new MyFilter1(), BasicAuthenticationFilter.class);
return http
.csrf().disable()
- 이번에는 SecurityFilterChain이 먼저 등록되는지, 내가 만든 필터가 먼저 등록이 되는지 확인해보기 위해 MyFilter3를 생성해서 SecurityFilterChain에 등록해줬다. 그리고 home으로 접근해서 우선순위를 확인해보자
- 위에 보이는 것처럼 SecurityFilterChain이 먼저 등록되는 것을 확인할 수 있다.
참고로, addFilterBefore대신에 addFilterAfter를 사용해도 결과는 똑같이 나온다.
- 그렇다면 모든 필터중에 내가 정의한 필터가 가장 먼저 동작하게 하고 싶다면?
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.addFilterBefore(new MyFilter3(), SecurityContextPersistenceFilter.class);
return http
.csrf().disable()
- 이렇게 정의하면 눈에 띄지는 않지만 내가 정의한 filter가 가장 먼저 동작하게 된다!!