상세 컨텐츠

본문 제목

SpringSecurity [DelegatingFliterProxy]

SpringSecurity

by 성찬우 2022. 6. 30. 23:29

본문

우리가 어떤 요청을 보내면 서블릿 컨테이너(톰캣)가 받는다.

서블릿 컨테이너에서는 서블릿 스팩을 지원하는데 필터라는 개념이 존재한다.

 

어떤 요청을 처리할 때 앞뒤로 특정한 일을 수행한다.

 

스프링에도 이런 서블릿 필터 구현체가 존재하는데 그 중하나가

DelegationFliterProxy 이다. (모든 필터가 서블릿필터 구현체라고 생각하면 된다고 한다. 하지만  DelegationFliterProxy 은 직접적으로 서블릿필터에 영향을 준다.)

 

Delegation 는 위임 - 선언 정도의 의미를 가지고있는데 

정말 말그대로 filter로서의 역할이 아닌 누군가에게 위임을 하는 역할을 한다. 

팀장님같은 존재다.

 

언제 위임?
서블릿 필터 처리를 스프링에 존재하는 빈으로 위임할 때.
(어떤 빈을 사용할지 구체적인 명시가 필요)->타겟 빈 이름 설정.
누구한테 위임?
FilterChainProxy
어떻게 위임?
스프링 부트를 사용 할 때에는 자동으로 등록 (SecurityFilterAutoConfiguration)
스프링 부트를 사용하지 않을 때에는 (AbstractSecurityWebApplicationInitializer 등록 필요)

 

SecurityFilterAutoConfiguration

 

설명 >>

스프링시큐리티 필터에 대한 Auto-configutaion .

사용자가 설정한(제공한) WebSecurityConfiguration이 존재한다면 필터의 순서가 보장되어 구성이 되도록SpringBootWebSecurityConfiguration과는 별도로 구성됩니다.

 

코드 보러가기 >>

더보기
@Configuration(proxyBeanMethods = false)
@ConditionalOnWebApplication(type = Type.SERVLET)
@EnableConfigurationProperties(SecurityProperties.class)
@ConditionalOnClass({ AbstractSecurityWebApplicationInitializer.class, SessionCreationPolicy.class })
@AutoConfigureAfter(SecurityAutoConfiguration.class)
public class SecurityFilterAutoConfiguration {

	private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;

	@Bean
	@ConditionalOnBean(name = DEFAULT_FILTER_NAME)
	public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration(
			SecurityProperties securityProperties) {
		DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(
				DEFAULT_FILTER_NAME);
		registration.setOrder(securityProperties.getFilter().getOrder());
		registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
		return registration;
	}

	private EnumSet<DispatcherType> getDispatcherTypes(SecurityProperties securityProperties) {
		if (securityProperties.getFilter().getDispatcherTypes() == null) {
			return null;
		}
		return securityProperties.getFilter().getDispatcherTypes().stream()
				.map((type) -> DispatcherType.valueOf(type.name()))
				.collect(Collectors.toCollection(() -> EnumSet.noneOf(DispatcherType.class)));
	}

}

약간의 메소드 설명 

private static final String DEFAULT_FILTER_NAME = AbstractSecurityWebApplicationInitializer.DEFAULT_FILTER_NAME;
------------------------------------------------[1]------------------------------------------
@Bean
@ConditionalOnBean(name = DEFAULT_FILTER_NAME)
public DelegatingFilterProxyRegistrationBean securityFilterChainRegistration( -------[2]
      SecurityProperties securityProperties) {
   DelegatingFilterProxyRegistrationBean registration = new DelegatingFilterProxyRegistrationBean(
         DEFAULT_FILTER_NAME);
   registration.setOrder(securityProperties.getFilter().getOrder());
   registration.setDispatcherTypes(getDispatcherTypes(securityProperties));
   return registration;
}

 

[1] DEFAULT_FILTER_NAME 은 AbstractSecurityWebApplicationInitialinzer.class에 선언이 되어있고 

public abstract class AbstractSecurityWebApplicationInitializer implements WebApplicationInitializer {

   private static final String SERVLET_CONTEXT_PREFIX = "org.springframework.web.servlet.FrameworkServlet.CONTEXT.";

   public static final String DEFAULT_FILTER_NAME = "springSecurityFilterChain";

기본 필터 이름값은 springSecurityFilterChain 이다. 

 

[2] DelegatingFilterProxyRegistrationBean

말그대로 DelegatingFilterProxy를 등록하는 빈이다(RegistrationBean)

메소드 밑에 생성자를 보면 [1]번을 그대로 사용하는 것을 볼 수 있다.

 


 

AbstractSecurityWebApplicationInitializer 

설명 >>등록된 다른 필터보다도 먼저 SpringSecurityFilterChain을 사용하도록 DeletatingFilterProxy 를 등록한다. 

 

AbstractSecurityWebApplicationInitializer.class 와 함께 사용할 경우 ContextLoaderListener도 등록한다.

 

AbstractSecurityWebApplicationInitializer()와 함께 사용할 경우 AbstractContextLoaderInitializer의 하위 클래스와 함께 사용된다. 

 

기본적으로 "DelegatingFilterProxy"는 지원 없이 등록되지만 'isAsyncSecuritySupported()' 및 'getSecurityDispatcherTypes()'를 재정의하여 활성화할 수 있다.

 

'spring SecurityFilterChain' 전후의 추가 구성은 'afterSpringSecurityFilterChain(ServletContext)'을 오버라이딩하여 추가할 수 있습니다.

 


우리에게는 FilterChainProxy 라는 것이 있는데 자동적으로 우리가 필요한 필터들을 골라 매치를 시켜 

필터로 사용되게 해주는 아주 편리한 아이다. 

 

결국 FilterChainProxy 도 DelegatingFilterProxy 라는 상사에게 일을 위임 받는 것이다. 

 

 

 

 

 

 

 

 

 

 

 

 

관련글 더보기

댓글 영역