# 스프링 시큐리티의 필터
- 스프링 시큐리티의 Http 필터는 일반적으로 요청에 적용해야 하는 각 책임을 관리하며 책임의 체인을 형성한다.
# 스프링 시큐리티 아키텍처의 필터 구현
- 스프링 시큐리티 아키텍처의 필터는 일반적으로 Http 필터다.
- 필터를 만들려면 javax.servlet 패키지의 Filter 인터페이스를 구현한다.
- doFilter() 메서드를 재정의해 논리를 구현해야 하고, 이 메서드는 ServletRequest, ServletResponse, FilterChain 매개 변수를 받는다.
# 체인에서 기존 필터 앞에 필터 추가
- 아래의 코드와 같이 addFilterBefore, addFilterAfter 메소드를 통하여 필터를 추가할 수 있다.
@Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(
new RequestValidationFilter(),
BasicAuthenticationFilter.class)
.addFilterAfter(
new AuthenticationLoggingFilter(),
BasicAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().permitAll() ;
}
# 필터 체인의 다른 필터 위치에 필터 추가
- 공통적으로 Client-Server가 특정 헤더 키 값을 가지고 통신하는 경우 아래와 같은 코드를 구성할 수 있다.
- @Component를 설정해서 빈으로 등록하였고 addFilterAt을 사용하여 특정 위치에 위치시켰다.
@Autowired
private StaticKeyAuthenticationFilter filter ;
@Override
public void configure(HttpSecurity http) throws Exception {
http.addFilterAt(filter, BasicAuthenticationFilter.class)
.authorizeRequests()
.anyRequest().permitAll() ;
}
@Component
public class StaticKeyAuthenticationFilter implements Filter {
@Value("${authorization.key}")
private String authorizationKey ;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
var httpRequest = (HttpServletRequest) request ;
var httpResponse = (HttpServletResponse) response ;
String authorization = httpRequest.getHeader("authorization1") ;
System.out.println("authorization : " + authorization) ;
if(authorizationKey.equals(authorization)) {
chain.doFilter(request,response);
} else {
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED) ;
}
}
}
# 스프링 시큐리티가 제공하는 필터 구현
- 스프링 시큐리티에는 Filter 인터페이스를 구현한느 여러 추상 클래스가 있으며, 이를 위해 필터 정의를 확장할 수 있다.
- GenericFilterBean 클레스를 활용하면 필요할 때 web.xml 설명자 파일에 정의하여 초기화 매개 변수를 이용할 수 있다.
- OncePerRequestFilter는 GenericFilterBean을 확장하는 더 유용한 클래스다.
- 프레임워크는 필터 체인에 추가한 필터를 요청당 한 번만 실행하도록 보장하지는 않는다.
- OncePerRequestFilter는 이름이 의미하듯이 필터의 doFilter() 메서드가 요청당 한 번만 실행되도록 논리를 구현했다.
- 사용 예시는 아래와 같다.
public class AuthenticationLoggingFilter extends OncePerRequestFilter {
private final Logger logger = Logger.getLogger(AuthenticationLoggingFilter.class.getName()) ;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String requestId = request.getHeader("Reqeust-id") ;
logger.info("Successfully authenticated reqeust with id " + requestId) ;
filterChain.doFilter(request,response) ;
}
}