FilterChainProxy
- springSecurityFilterChain 의 이름으로 생성되는 필터 빈이며, Security Filter 들을 관리하는 빈이다.
- DelegatingFilterProxy 으로 부터 요청을 위임 받고 실제 보안 처리한다.
- 스프링 시큐리티 초기화 시 생성되는 필터들을 관리하고 제어한다.
- FilterChainProxy는 요청에 따라 적합한 SecurityFilterChain 을 사용한다.
- 기본 전략으로 DefaultSecurityFilterChain을 사용한다. -> DefaultSecurityFilterChain 는 Filter 리스트를 가지고 있다.
- 사용자의 요청을 필터 순서대로 호출하여 전달한다.
- 사용자정의 필터를 생성해서 기존의 필터 전.후로 추가 가능하다.
- 아래에서 설정한 SecurityConfig 에서 설정한 값에 따라서 SecurityFilterChain 가 만들어지고, 만들어진 Chain 에 따라서 Filter 리스트가 다르다.
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/", "/info").permitAll()
.mvcMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated();
http.formLogin();
http.httpBasic();
}
}
- SecurityFilterChain 를 여러개 만들고 싶으면 SecurityConfig를 여러개 만들어주면 된다.
- 우선순위를 정해주고 싶으면 @Order 애노테이션을 사용할 수 있다.
- 우선순위를 지정해 줄때 포괄적인 설정을 먼저 두면, 상세한 설정이 먹히기 때문에 주의해야한다.
- "/**" 를 "/admin" 보다 먼저 두면 안된다.
- SecurityConfig 인 구조는 아래와 같다.
- 위와 같이 SecurityConfig 별로 만들어진 Filter 리스트 들은 securityFilterChains 에 담긴다.
- FilterChainProxy 는 Filter 리스트에서 필터를 호출하는데, 필터의 종류는 아래와 같다. -> 설정에 따라 달라질 수 있다.
1. WebAsyncManagerIntergrationFilter 2. SecurityContextPersistenceFilter 3. HeaderWriterFilter 4. CsrfFilter 5. LogoutFilter 6. UsernamePasswordAuthenticationFilter 7. DefaultLoginPageGeneratingFilter 8. DefaultLogoutPageGeneratingFilter 9. BasicAuthenticationFilter 10. RequestCacheAwareFilter 11. SecurityContextHolderAwareReqeustFilter 12. AnonymouseAuthenticationFilter 13. SessionManagementFilter 14. ExeptionTranslationFilter 15. FilterSecurityInterceptor
- 위의 필터중 SecurityContextPersistenceFilter, UsernamePasswordAuthenticationFilter 는 Authentication 객체를 관리한다.
- UsernamePasswordAuthenticationFilter
- 폼 인증을 처리하는 시큐리티 필터다.
- 인증된 Authentication 객체를 SecurityContextHolder에 넣어주는 필터다.
- SecurityContextPersistenceFilter
- SecurityContext를 HTTP session에 캐시(기본 전략)하여 여러 요청에서 Authentication을 공유하는 필터다.
- SecurityContextRepository를 교체하여 세션을 HTTP session 이 아닌 다른 곳에 저장하는 것도 가능하다.
- 만약 SecurityContextPersistenceFilter 를 사용하지 않는다면? -> UsernamePasswordAuthenticationFilter 혹은 다른 필터를 사용해서 매 요청시 인증을 처리해야하고, 그 내용을 http 헤더나 본문에 포함해야 한다.
- 만약 인증이 필요한 페이지에서 새로고침을 한다면? -> SecurityContextFilter 가 Security Context 를 꺼내준다. -> Http 세션이 달라지면 꺼내 올 수 없다.
DelegatingFilterProxy
- 일반적인 서블릿 필터중 하나이다.
- 서블릿 필터 처리를 스프링에 들어있는 빈으로 위임하고 싶을 때 사용하는 서블릿 필터이다.
- 그럼 DelegatingFilterProxy 가 필요한 이유는 무엇일까?
- 서블릿 필터는 스프링에서 정의된 빈을 주입해서 사용할 수 없다.
- 특정한 이름을 가진 스프링 빈을 찾아서 그 빈에게 요청을 위임 해야한다.
- DelegatingFilterProxy 는 타겟 빈 이름을 설정하는데, 아래와 같이 FilterChainProxy는 springSecurityFilterChain 이름으로, 빈으로 등록된다.
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";
...
}
- 스프링 부트를 사용할 때는 자동으로 등록된다. (SecurityFilterAutoConfiguration)
- 스프링 부트 없이 스프링 시큐리티 설정할 때는 AbstractSecurityWebApplicationInitializer를 사용해서 등록해야 한다.
- 따라서 springSecurityFilterChain 이름으로 생성된 빈을 ApplicationContext 에서 찾아 요청을 위임한다.
REFERENCES
- 백기선님의 스프링 시큐리티
- 정수원님의 스프링 시큐리티
'Spring Security' 카테고리의 다른 글
CustomAuthenticationProvider (0) | 2022.02.28 |
---|---|
AuthenticationManager 와 AuthenticationProvider (0) | 2022.02.28 |
Security Config (0) | 2022.02.28 |
SecurityContextHolder, AuthenticationManager, ThreadLocal (0) | 2022.02.28 |
스프링 시큐리티 아키텍처 (0) | 2022.02.28 |