톰캣을 서블릿 컨테이너라고도 불리는데 다수의 서블릿으로 톰캣이 구성되어 있기 때문이다. spring에서 모든 요청은 dispatcherServlet에서 처음 처리를 시작하는데, 그 이전에 filter를 거쳐야 한다.
이 filter들은 chain으로 연결되어 있고, 반드시 모든 요청들은 이 filter를 하나하나씩 다 거쳐야 한다. 이 때 스프링 시큐리티 필터가 작동한다.
경우에 따라서 다양한 필터 정책을 적용할 수 있으며 역할은 시큐리티에서 DelegatingFilterProxy가 한다. 이 필터를 메인 필터에 끼우고, 그 아래에 여러개의 SeurityFilterChain을 등록한다. 각 필터 체인의 적용 경로는 /api/**, /admin/** 등 다양한 정책의 경우를 적용할 수 있다.
WebSecurityConfigurerAdapter 클래스가 SecurityFilterChain을 구성하는 클래스이다.
스프링 시큐리티 필터는 굉장히 많다. 각기 다른 관심사를 가지고 자신의 관심사를 해결한다. 필터를 넣거나 뺄 수 있으며, 적용되는 순서도 조절할 수 있다.(이 떄 필터의 순서는 굉장히 중요하기 때문에 기본 필터들은 순서들이 어느정도 정해져있다.)
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests((requests) ->
requests.antMatchers("/")
.permitAll()
.anyRequest()
.authenticated()
);
http.formLogin();
http.httpBasic();
}
이 설정으로 SecurityFilterChain의 필터들이 정해진다는 사실을 알았다. @EnableWebSecurity(debug = true)이기 떄문에 필터 체인 실행 정보가 콘솔에 기록된다.
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
* 만약에 configure 내부의 필터 설정을 주석처리 한다면?
@Override
protected void configure(HttpSecurity http) throws Exception {
//http.authorizeRequests((requests) ->
// requests.antMatchers("/")
// .permitAll()
// .anyRequest()
// .authenticated()
//);
//http.formLogin();
//http.httpBasic();
}
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
]
작동하는 필터의 갯수가 줄어들었다.
제외된 필터 목록은 다음과 같다.
Security filter chain: [
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
BasicAuthenticationFilter
FilterSecurityInterceptor
]
추가적으로 headers(), csrf(), logout(), requestCache()를 disable() 시키면 필터 체인에서 필터가 더 줄어든다.
@Override
protected void configure(HttpSecurity http) throws Exception {
// http.authorizeRequests((requests) ->
// requests.antMatchers("/")
// .permitAll()
// .anyRequest()
// .authenticated()
// );
// http.formLogin();
// http.httpBasic();
http
.headers().disable()
.csrf().disable()
.logout().disable()
.requestCache().disable();
}
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
]
* 다양한 필터 체인중에 경로 설정은 어떻게 하는가?
@Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher("/**");
http.authorizeRequests((requests) ->
requests.antMatchers("/")
.permitAll()
.anyRequest()
.authenticated()
);
http.formLogin();
http.httpBasic();
}
antMatchers를 활용한다.
* 2개 이상의 필터 체인을 적용하고 싶다고 하면 어떻게 하면 되는가?
시큐리티 필터 체인을 1개 더 생성하면 된다. 대신, 체인의 순서가 중요하드로 클래스 위에 @Order(1), @Order(2) 처럼 순서를 잘 정한다.