개발자의 오르막

[SpringSecurity #06] 스프링 시큐리티 Filter와 FilterChainProxy 본문

SpringFrameWork/SpringSecurity

[SpringSecurity #06] 스프링 시큐리티 Filter와 FilterChainProxy

계단 2020. 9. 27. 14:22

# 스프링 시큐리티가 제공하는 필터들

- WebAsyncManagerIntergrationFilter

- SecurityContextPersistenceFilter

- HeaderWriterFilter

- CsrfFilter

- LogoutFilter

- UsernamePasswordAuthenticationFilter

- DefaultLoginPageGeneratingFilter

- DefaultLogoutPageGeneratingFilter

- BasicAuthenticationFilter

- RequestCacheAwareFilter

- SecurityContextHolderAwareRequestFilter

- AnonymousAuthenticationFilter

- SessionManagementFilter

- ExeptionTranslationFilter

- FilterSecurityInterceptor

 

이 모든 필터는 FilterChainProxy 가 호출한다.

 

# FilterChainProxy

/**
	 * Returns the first filter chain matching the supplied URL.
	 *
	 * @param request the request to match
	 * @return an ordered array of Filters defining the filter chain
	 */
	private List<Filter> getFilters(HttpServletRequest request) {
		for (SecurityFilterChain chain : filterChains) {
			if (chain.matches(request)) {
				return chain.getFilters();
			}
		}

		return null;
	}

  getFilters 를 통해 해당 체인들의 목록을 가져온다.

  이러한 필터들은 SecurityConfig 파일의 소스를 근거로 가져오게 된다. (15개중 해당 필터만)

 

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final AccountService accountService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .mvcMatchers("/", "/info", "/account/**").permitAll()
                .mvcMatchers("/admin").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .and()
            .httpBasic();
    }

  위를 근거로 SecurityFilterChain 을 생성함

 

 

서블릿(톰캣) 에서 제공하는 기본 메소드 들이 있다. ( init, doFilter )

 

# DelegatingFilterProxy

- 일반적인 서블릿 필터

- 서블릿 필터 처리를 스프링에 들어있는 빈으로 위임하고 싶을 때 사용하는 서블릿 필터

- 타겟 빈 이름을 설정한다.

- 스프링 부트 없이 스프링 시큐리티 설정할 때는 AbstractSecurityWebApplicationInitializer를

  사용해서 등록

- 스프링 부트를 사용할 때는 자동으로 등록한다. ( SecurityFilterAutoConfiguration )

 

@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)));
	}

}

 

 

# FilterChainProxy

- 보통 springSecurityFilterChain 이라는 이름의 빈으로 등록된다.

 

 

- 직접 서블릿에 등록되는 Filter 는 DelegatingFilterProxy 이다.

  다른 필터들은 프로젝트 내에서 활용된다.

 

 

- SpringContextHolder 가 Authentication 을 가지고 있고, ( 로그인 정보 )

  AuthenticationManager 가 Authentication을 인증을 해주고,

  인증된 Authentication 을 다시 SpringContextHolder 에 넣어주고,

  넣어 줄 때 관련된 여러가지 Filter 를 거친다.

  여러가지 Filter 들은 FilterChainProxy 가 관리해주고 있고,

  DelegatingFilterProxy 를 통해 FilterChainProxy 가 들어오고 있다.

 

 

Comments