Server🧤/SpringSecurity

[SpringSecurity] Security Filter와 SecurityContextPersistenceFilter

yujindonut 2023. 7. 13. 18:54
728x90

Filter

필터는 요청이나 응답 또는 둘 다에 대해 필터링 작업을 수행하는 개체 

필터는 doFilter 메소드에서 필터링을 수행한다

Filter는 doFilter를 구현해야함

public interface Filter {
	public default void init(FilterConfig filterConfig) throws ServletException {}
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException;
	public default void destroy() {}
}

 

Filter가 적용되는 방법
Filter가 여러개일 경우

FilterChainProxy Class

private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		FirewalledRequest firewallRequest = this.firewall.getFirewalledRequest((HttpServletRequest) request);
		HttpServletResponse firewallResponse = this.firewall.getFirewalledResponse((HttpServletResponse) response);
		List<Filter> filters = getFilters(firewallRequest);
		if (filters == null || filters.size() == 0) {
			if (logger.isTraceEnabled()) {
				logger.trace(LogMessage.of(() -> "No security for " + requestLine(firewallRequest)));
			}
			firewallRequest.reset();
			chain.doFilter(firewallRequest, firewallResponse);
			return;
		}
		if (logger.isDebugEnabled()) {
			logger.debug(LogMessage.of(() -> "Securing " + requestLine(firewallRequest)));
		}
		VirtualFilterChain virtualFilterChain = new VirtualFilterChain(firewallRequest, chain, filters);
		virtualFilterChain.doFilter(firewallRequest, firewallResponse);
}

getFilters(firewallRequest); 를 디버깅해보자!

Filter의 순서를 알 수 있다.

 

 


Filter의 순서

순서를 보려면 FilterOrderRegistration 를 봐야한다.

Filter들은 100번 부터 시작해서 100씩 증가된다. 즉, 100이 가장먼저 200, 300, 400 이런 순서대로 필터가 적용됩니다.
굳이 이렇게 만든 이유는 100이라는 공백 사이사이에 커스텀 필터를 넣을 수 있도록 한 것입니다.

private static final int INITIAL_ORDER = 100;
private static final int ORDER_STEP = 100;
private final Map<String, Integer> filterToOrder = new HashMap<>();
FilterOrderRegistration() {
	Step order = new Step(INITIAL_ORDER, ORDER_STEP); put(ChannelProcessingFilter.class, order.next());
	order.next(); 
	put(WebAsyncManagerIntegrationFilter.class, order.next());
	put(SecurityContextPersistenceFilter.class, order.next());
}

Spring Security의 동작은 Filter로 동작한다.

필터에 동작하는 순서를 정해줘서 원하는대로 유기적으로 동작할 수 있다.

많이 쓰이는 FIlter는 아래와 같다.

SecurityContextPersistenceFilter
BasicAuthenticationFilter
UsernamePasswordAuthenticationFilter
CsrfFilter
RememberMeAuthenticationFilter
AnonymousAuthenticationFilter
FilterSecurityInterceptor
ExceptionTranslationFilter

SecurityContextPersistenceFilter를 보면 아래처럼 GenericFilterBean를 상속하고 있고 GenericFilterBean는 Filter를 상속한다.

‼️ SecurityContextPersistenceFilter는 Filter를 구현한다.

public class SecurityContextPersistenceFilter extends GenericFilterBean {
public abstract class GenericFilterBean implements Filter

SpringSecurity에는 다양한 Filter들이 존재하는데 그중에 하나가 SecurityContextPersistenceFilter이다. 


SecurityContextPersistenceFilter

  • SecurityContextPersistenceFilter는 보통 두번째로 실행되는 필터 아키텍처
  • SecurityContextPersistenceFilter는 SecurityContext를 찾아와서 SecurityContextHolder에 넣어주는 역할을 하는 Filter
  • SecurityContext를 찾았는데 없다면 그냥 새로 하나 생성해준다.

첫번째로 실행되는 필터는 Async 요청에 대해서도 SecurityContext를 처리할수 있도록 해주는 WebAsyncManagerIntegrationFilter

public class SecurityContextPersistenceFilter extends GenericFilterBean {
	private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
		throws IOException, ServletException {
		SecurityContext contextBeforeChainExecution = this.repo.loadContext(holder);
        try {
			SecurityContextHolder.setContext(contextBeforeChainExecution);
			chain.doFilter(holder.getRequest(), holder.getResponse());
		}
		finally {
			SecurityContext contextAfterChainExecution = SecurityContextHolder.getContext();
			// Crucial removal of SecurityContextHolder contents before anything else.
			SecurityContextHolder.clearContext();
			this.repo.saveContext(contextAfterChainExecution, holder.getRequest(), holder.getResponse());
		} 
	}
}

HttpSession

SecurityContextPersistenceFilter는 SecurityContext가 있으면 그걸 사용하고 없다면 새로 생성한다.

SecurityContext가 있는지 없는지 확인을 HttpSession에서 가져온다.

 

728x90