DelegatingFilterProxy & FilterChainProxy
ServletFilter
-
WAS에서 톰캣이 올라가서 WAS에서 실행되는 필터이다.
요청을 받아서 Servlet에 전달하고, Servlet에서 응답을 받아서 클라언트에 전달하는 역할을 수행한다. -
Servlet Container에서 생성되고 실행이 된다.
-
Servlet Filter는 스프링에서 정의된 빈을 주입해서 사용할 수 없다.
-> 서로 실행되는 컨테이너가 다르기 때문
인증/인가 처리는 스프링 컨테이너에 생성된 Filter를 통해서 처리된다.
실질적인 서블릿 필터가 DelegatingFilterProxy이다.
// web.xml
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>springSecurityChain</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
DelegatingFilterProxy
-
서블릿 컨테이너와 스프링 컨테이너(어플리케이션 컨텍스트) 사이의 링크를 제공하는 ServletFilter이다.
-
특정한 이름을 가진 스프링 빈을 찾아 그 빈에게 요청을 위임한다.
-> 서블릿 필터(서블릿 컨테이너)와 시큐리티 필터(스프링 컨테이너)는 서로 다른 컨테이너에서 생성되고 동작한다. -
요청 순서
- Servlet Filter가 요청을 DelegatingFilterProxy로 전달한다.- DelegatingFilterProxy는 해당 요청을 스프링 컨테이너에 생성 된 Filter를 구현한 스프링 빈에 위임한다.
- springSecurityFilterChain 이름으로 생성된 빈을 ApplicationContext에서 찾아 위임을 요청(실제 보안 처리를 하지 않음)
- SecurityFilterAutoConfiguration 클래스에서 DelegatingFilterProxyRegistrationBean를 빈으로 등록한다.
// SecurityFilterAutoConfiguration
@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;
}
- DelegatingFilterProxyRegistrationBean 클래스 DelegatingFilterProxy 객체를 생성한다.
// DelegatingFilterProxyRegistrationBean
@Override
public DelegatingFilterProxy getFilter(){
return new DelegatingFilterProxy(this.targetBeanName, getWebApplicationContext()){
@Override
protected void initFilterBean() throws ServletException{
// Don't initialize filter bean on init()
}
};
}
- this.setTargetBeanName(targetBeanName) DelegatingFilterProxy로 요청이 들어올 때 처리를 위임 할 스프링 빈 이름(springSecurityFilterChain)을 설정한다.
// DelegatingFilterProxy
public DelegatingFilterProxy(String targetBeanName, @Nullable WebApplicationContext wac){
Assert.hasText(targetBeanName, "Target Filter bean name must not be null or empty");
this.setTargetBeanName(targetBeanName);
this.webApplicationContext = wac;
if (wac != null){
this.setEnvironment(wac.getEnvironment());
}
}
- 요청이 들어오면 가장 먼저 DelegatingFilterProxy의 doFilter() 함수가 호출된다. doFilter() 함수는 요청을 위임할 필터(springSecurityFilterChain)을 찾아서 해당 요청을 위임(invokeDelete())한다.
// DelegatingFilterProxy
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws ServletExcpetion, IOException{
// Lazily nitialize 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);
}
- invokeDelete() 함수 호출 시 내부에서 FilterChainProxy의 doFilter() 함수를 호출하고, doFilterInternal() 함수에서는 등록 된 Filter 목록을 가지고 인증/인가 처리를 진행한다.
// FilterChainProxy
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException{
boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
if(clearContext){
try{
request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
doFilterInternal(request, response, chain);
}
finally{
SecurityContextHolder.clearContext();
request.removeAttribute(FILTER_APPLIED);
}
}else{
doFilterInternal(request, response, chain);
}
}
FilterChainProxy
- springSecurityFilterChain의 이름으로 생성되는 필터 빈이다.
- DelegatingFilterProxy로부터 요청을 위임 받고 실체로 보안을 처리한다.
- 스프링 시큐리티 초기화 시 생성되는 필터들을 관리하고 제어한다.
- 스프링 시큐리티가 기본적으로 생성하는 필터
- WebAsyncManager
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- LogoutFilter
- AnonymousAutehnticationFilter
- SessionManagementFilter
-> 사용자의 요청을 필터 순서대로 호출하여 전달한다.
사용자 정의 필터를 생성해서 기존의 필터 전후로 추가 가능하다.
마지막 필터까지 인증 및 인가 예외가 발생하지 않으면 보안을 통과한다.
/**
Creates the Spring Security Filter Chain
@return the {@link Filter} that represents the security filter chain
@throws Exception
*/
@Bean(name = AbstractSecurityWebApplicationInitailizer.DEFAULT_fILTER_NAME)
public Filter springSecurityFilterChain() throws Exception{
boolean hasConfigurers = webSecurityConfigurers != null && !webSecurityConfigurers.isEmpty();
if(!hasConfigurers){
WebSecurityConfigurerAdapter adapter = objectObjectPostProcessor.postProcess(new WebSecurityConfigurerAdapter(){});
webSecurity.apply(adapter);
}
return webSecurity.build();
}
- webSecurity.build() 함수 호출 시 springSecurityFilterChain이름의 FilterChainProxy 빈을 생성한다.
Author And Source
이 문제에 관하여(DelegatingFilterProxy & FilterChainProxy), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@bey1548/DelegatingFilterProxy-FilterChainProxy저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)