Spring Security Filter Chain
Spring Security 의 Filter 들은 Spring Container 에서 Spring Bean 으로 등록되어 있다.
하지만 Filter 들은 Servlet Container 에서 동작하는걸로 알고 있지만
Spring Container 와 Servlet Container 는 영역 자체가 다르기 때문에 어떻게 실행되는지 궁금해서
정리하게 됐다.
위 이미지처럼 Servlet Container 와 Spring Container 는 영역 자체가 다르며, Filter 는 서블릿이 제공하는 기술이다.
Spring Bean 으로 등록되어 있는 Filter 들은 DelegatingFilterProxy 라는 클래스를 통해
Spring Bean Filter 들을 실행시킨다. DelegatingFilterProxy 는 표준 서블릿 필터용 프록시이다.
사용자의 요청이 들어오면 서블릿 컨테이너에서 생성되고 실행되는 DelegatingFilterProxy 가
SpringSecurityFilterChain 이라는 Spring Bean 을 ApplicationContext 에서 찾는다.
bean 을 찾으면 SpringSecurityFilterChain 으로 요청을 위임한다.
아래는 DelegatingFilterProxy 이다.
1. ApplicationContext 불러온다.
2. initDelegate() 메서드를 통해 ApplicationContext 내에 있는 Bean 들을 가져온다.
3. invokeDelegate() 메서드를 통해 Filter 들을 실행시킨다.
public class DelegatingFilterProxy extends GenericFilterBean {
...
@Nullable
private WebApplicationContext webApplicationContext;
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
// Lazily initialize the delegate if necessary.
Filter delegateToUse = this.delegate;
if (delegateToUse == null) {
synchronized (this.delegateMonitor) {
delegateToUse = this.delegate;
if (delegateToUse == null) {
WebApplicationContext wac = findWebApplicationContext();
if (wac == null) {
throw new IllegalStateException("No WebApplicationContext found: " +
"no ContextLoaderListener or DispatcherServlet registered?");
}
delegateToUse = initDelegate(wac);
}
this.delegate = delegateToUse;
}
}
// Let the delegate perform the actual doFilter operation.
invokeDelegate(delegateToUse, request, response, filterChain);
}
protected Filter initDelegate(WebApplicationContext wac) throws ServletException {
String targetBeanName = getTargetBeanName();
Assert.state(targetBeanName != null, "No target bean name set");
Filter delegate = wac.getBean(targetBeanName, Filter.class);
if (isTargetFilterLifecycle()) {
delegate.init(getFilterConfig());
}
return delegate;
}
protected void invokeDelegate(
Filter delegate, ServletRequest request, ServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
delegate.doFilter(request, response, filterChain);
}
...
}
Security Filter Chain
DelegatingFilterProxy 는 서블릿 컨테이너(WAS) 에서 생성되고 실행된다.
Spring Container 에서 사용되는 Spring Bean 은 Spring 에서 사용되며, Servlet 에서 사용될 수 없다.
이렇게 Spring 에서 사용되는 Filter 들을 Servlet 에서 사용하기 위해선 DelegatingFilterProxy 가
사용자 요청을 받아 Spring Security Filter Chain 에게 위임하여 실행한다.
중요 Filter 정리
SecurityContextPersistenceFilter
SecurityContextRepository 에서 SecurityContext 를 가져오거나 생성하는 역할을 한다.
SecurityContextPersistenceFilter 는 무조건적으로 SecurityContext 의 변경여부에 상관없이
인증이 완료되면 SecurityContextRepository 에 SecurityContext 를 저장한다.
... // SecurityContextPersistenceFilter.class
finally {
SecurityContext contextAfterChainExecution = this.securityContextHolderStrategy.getContext();
// Crucial removal of SecurityContextHolder contents before anything else.
this.securityContextHolderStrategy.clearContext();
this.repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
request.removeAttribute(FILTER_APPLIED);
this.logger.debug("Cleared SecurityContextHolder to complete request");
}
Spring Security 6 버전부터는 SecurityContextPersistenceFilter 가 Deprecated 되고
SecurityContextHolderFilter 가 사용된다.
SecurityContextPersistenceFilter 와 비슷하지만 SecurityContextHolder 에서 SecurityContext 를 가져와
SecurityContexrRepository 에 save 하는 과정을 직접 코드에서 추가해줘야 한다.
UsernamePasswordAuthenticationFilter
Spring Security Default 사용자 인증 필터이다.
UsernamePasswordAuthenticationFilter 는 Form Based Authentication 방식 인증 필터이다.
AuthenticationManager, AuthenticationProvider, UserDetails 객체, UserDetailsService 등
Spring Security 에서 기본적으로 제공하는 클래스 및 인터페이스를 통해
인증을 시도한다.
SessionManagementFilter
Spring Security 에서 Session 을 제어하기 위한 Filter 이다.
1. 세션관리 : 인증 후 사용자의 세션 관리(등록, 조회, 삭제)
2. 동시 세션 제어 : 동일 계정에 대한 세션 관리
3. 세션 고정 보호 : 인증 후 세션 쿠키를 재발급하여 세션 쿠키 조작 공격을 방지
4. 세션 생성 정책 : Always, If_Required, Never, Stateless
SessionManagementFilter 는 SessionAuthenticationStrategy 세션 관련 전략에 따라 세션을 관리한다.
CompositeSessionAuthenticationStrategy
모든 SessionAuthenticationStrategy 를 불러와 오버라이드 된 onAuthentication() 메서드를 실행한다.
ConcurrentSessionControlAuthenticationStrategy
동시적 세션 제어를 위한 Session Strategy 이다.
최대 세션 개수 및 동시적 로그인이 발생했을 때의 제어방식을 설정한다.
RegisterSessionAuthenticationStrategy
새로운 세션을 등록한다.
ConcurrentSessionFilter
동시적 세션제어를 하는 필터이다.
SessionManagementFilter 와 연계하여 세션을 만료시키고 동시적 세션을 제어한다.