스프링시큐리티의 큰그림
서블릿 컨테이너
- 톰캣과 같은 웹 애플리케이션을 서블릿 컨테이너라고 부르는데, 이런 웹 애플리케이션(J2EE Application)은 기본적으로 필터와 서블릿으로 구성되어 있다.
- 필터는 체인처럼 엮여있기 때문에 필터 체인이라고도 불리는데, 모든 request는 이 필터 체인을 반드시 겨쳐야만 서블릿 서비스에 도착하게 된다.
스프링 시큐리티의 큰 그림
- 그래서 스프링 시큐리티는 DelegatingFilterProxy라는 필터를 만들어 메인 필터체인에 끼워넣고, 그 아래 다시 SecurityFilterChain 그룹을 등록한다.
- 이 필터체인은 반드시 한 개 이상이고, url 패턴에 따라 적용되는 필터 체인을 다르게 할 수 있다. 본래의 메인 필터를 반드시 통과해야만 서블릿에 들어갈 수 있는 단점을 보완하기 위해서 필터체인인 Proxy를 두었다고 할 수 있다.
- 이때 @Order 어노테이션을 통해 필터 체인의 우선순위를 지정할 수 있다. 숫자가 낮을 수록 우선순위가 높다.
@Order(1)
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
- web resource의 경우 패턴을 따르더라도 필터를 무시(ignore)하고 통과시켜주기도 한다.
시큐리티 필터들
- 각각의 필터는 각기 서로 다른 관심사를 해결한다.
- HeaderWriterFilter : Http 헤더를 검사한다. 응답 헤더에 써야할 건 잘 써있는지, 필요한 헤더를 더해줘야 할 건 없는지 검사한다.
- CorsHeader : 허가된 사이트나 클라이언트의 요청인지 검사한다.
- CsrfFilter : 내가 내보낸 리소스에서 올라온 요청인지 검사한다.
- LogoutFilter : 로그아웃하겠다고 하는건지 검사한다.
- UsernamePasswordAuthenticationFilter : username / password로 로그인을 하려는지 검사한다. 만약 로그인이면 여기서 처리하고 가야할 페이지로 보내준다.
- ConcurrentSessionFilter : 여기저기서 로그인하는 걸 허용할 것인지 설정한다.
- BearerTokenAuthenticationFilter : Authorization 헤더에 Bearer 토큰이 오면 인증처리해준다.
- BasicTokenAuthenticationFilter : Authorizatino 헤더에 Basic 토큰이 오면 인증처리해준다.
- RequestCacheAwareFilter : 방금 요청한 request 이력이 다음에 필요할 수도 있으니 캐시에 담아놓는다.
- SecurityContextHolderAwareRequestFilter : 보안 관련 Servlet 3 스펙을 지원하기 위한 필터이다.
- RememberMeAuthenticationFilter : 아직 Authentication 인증이 안된 경우라면 RememberMe 쿠키를 검사해서 인증 처리해준다.
- AnonymousAuthenticationFilter : 아직 인증이 안되었으면 Anonymous 사용자라고 판단한다.
- SessionManagementFilter : 서버에서 지정한 세션정책을 검사한다.
- ExceptionTranslationFilter : 인증이나 권한 예외가 발생하면 잡아서 처리한다.
- FilterSecurityInterceptor : 이 필터까지 왔으면 인증이 있다는 것이니, 보낸 request에 들어갈 자격이 있는지 그리고 리턴한 결과를 보내줘도 되는지 마지막으로 점검한다.
- 그 밖에 OAuth2나 Saml2, Cas, X509에 관한 필터들도 있다.
- 필터는 넣거나 뺄 수 있고 순서를 조절할 수도 있다. (이때 필터의 순서가 매우 critical할 수 있기 때문에 기본 필터들은 그 순서가 어느정도 정해져 있다.)
요청을 보냈을 때 어떤 필터가 사용되었는지 확인하기 위해서는 @EnableWebSecurity(debug = true) 어노테이션을 사용하면 된다.
@Order(1)
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
참고
- 패스트 캠퍼스 : Java/Spring 웹 개발 마스터 초격차 패키지