Spring Security는 Spring MVC 영역 전에 작업이 수행됩니다.
Spring MVC를 공부하면서 자주 보게되는 Spring MVC flow chart인데요. 위 차트에서는 Incoming request가 바로 Front Controller(=Dispatcher Servlet)으로 전달되는 것으로 표현되어 있습니다. 맞는 말이지만 사실 Front Controller에 전달되기 전에 'Filter'라는 것들을 거치게 됩니다.
보라색 상자로 표현된 Client가 웹브라우저로 HttpRequest를 보내면,
Servlet Container는 'FilterChain'이라는 Filter들이 연결되어 순서대로 실행될 수 있는 체인을 생성합니다. (Filter Chain은 Servlet Container 안에 존재합니다.) FilterChain 안에는 Filter만 있는 것이 아니라 해당 request를 처리할 수 있는 Servlet도 같이 들어있습니다. 이 Servlet이 바로 Dispatcher Servlet인데, 체인 순서 중 가장 마지막에 있습니다.
Filter는 순서에 맞추어 작동하는 것이 중요하기 때문에 그 순서가 지정되어 있습니다. 순서가 중요한 Filter에서 Servlet이 가장 나중에 위치 하고 있다는 의미는 모든 Filter 처리가 다 마무리된 이후에 비로소 Servlet으로 요청이 전달되어야 한다는 의미이겠습니다.
왜 갑자기 Filter들에 대해서 이야기를 하느냐 하면,
앞에서 Spring security는 Spring MVC영역 전에 수행된다고 하였습니다.
그런데 Spring MVC 영역 전에 있는게 어떤 과정이었죠? 바로 Filter처리 입니다. Spring Security 역시 이 Filter 처리 단에서 Filter로서 역할 수행을 하게 됩니다. 보안 처리를 위한 Filter를 만들어서 말이죠! Spring Security가 만든 Filter들은 Bean으로 Application Context에서 관리가 됩니다.
한 가지 문제는 Filter들이 담겨있는 Servlet Container 는 Spring Security의 Application Context에 있는 Bean filter들을 저절로 인식하지는 못한다는 점입니다. Servlet Container와 Application Context는 독립된 공간이고 연결점이 없기 때문입니다.
Spring Security가 보안작업을 수행해 줄 filter들을 열심히 만들었는데, 적용이 될 수 있게 해주어야겠죠?
이 때 적용을 도와주는 것이 DelegatingFilterProxy입니다. 이름도 Delegating(위임, 일을 대신해준다는 뜻)에 proxy(중간 다리역할 한다는 뜻)까지 붙어있으니 뭔가 중간에서 무언가를 대신해주는 친구라는 느낌이 딱 듭니다.
DelegatingFilterProxy의 도움을 받아서 Filter Chain내부에 자리를 잡았고, 이제 Security filter도 수행할 수 있어야 합니다. 이때 FilterChainProxy라는 Bean이 SecurityFilterChain을 통해 Security Filter 들에 역할을 수행하도록 합니다. (= 역할 수행을 위임delegate한다) FilterChainProxy는 DelegatingFilterProxy로 감싸져 있습니다.
FilterChainProxy가 사용하는 SecurityFilterChain은 여러 Spring Security Filter 중에서 (요청에 맞게) 어떤 filter를 동작시킬 것인지를 결정해줍니다. 굳이 FilterChainProxy라는 것을 사용해서 filter를 동작하는 이유는 무엇일까요? 바로 몇 가지 이점이 있기 때문입니다.
- 한 가지는 Spring Security의 Servlet support의 시작점이기 때문에 Servlet support를 트러블 슈팅하고 싶다면 FilterChainProxy에 break point를 걸어두고 확인할 수 있습니다.
- 메모리 leak 방지를 위해 Security Context를 비우는 등의 역할도 수행합니다.
- 어떤 Security Filter가 사용되어야 할지 결정해줍니다. request의 URL path를 보고 적용될 Security Filter를 결정합니다. 아래의 도표를 보시면 좀 더 이해가 잘 되실 것 같습니다.
=> 예를 들어, request url이 /api/user 였다면 FilterChainProxy는 SecurityFilterChain0이 동작하게 할 것입니다.
이렇게 어떻게 Spring Security가 동작하는지 알아보았습니다.
정리를 해보자면 아래 내용이 핵심적인 내용들인 것 같습니다.
- Servlet Container의 Filter 쪽에서 security 작업이 수행되고 spring security 역시나 filter 형태로 되어있다.
- 그리고 servlet이 spring filter bean이 담겨있는 spring context를 인식하지 못하는데, DelegatingFilterProxy가 그 둘을 연결해준다.
- Security bean들은 FilterChainProxy에 의해 동작하게 된다.
- Security bean들은 SecurityFilterChain에 들어있고, client의 request에 따라 알맞은 SecurityFilterChain을 FilterChainProxy가 동작시킨다.
Security Filter의 종류는 아래처럼 많고 다양합니다. (모든 필터들을 다 알 필요는 없지만 중요한 기능을 하는 필터는 알고 있으면 동작을 이해하기 더 편한 것 같습니다)
Custom filter를 만들어서 Security filter들 중 원하는 위치에서 동작하게 할 수도 있습니다.
- ForceEagerSessionCreationFilter
- ChannelProcessingFilter
- WebAsyncManagerIntegrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- CorsFilter
- CsrfFilter
- LogoutFilter
- OAuth2AuthorizationRequestRedirectFilter
- Saml2WebSsoAuthenticationRequestFilter
- X509AuthenticationFilter
- AbstractPreAuthenticatedProcessingFilter
- CasAuthenticationFilter
- OAuth2LoginAuthenticationFilter
- Saml2WebSsoAuthenticationFilter
- UsernamePasswordAuthenticationFilter
- OpenIDAuthenticationFilter
- DefaultLoginPageGeneratingFilter
- DefaultLogoutPageGeneratingFilter
- ConcurrentSessionFilter
- DigestAuthenticationFilter
- BearerTokenAuthenticationFilter
- BasicAuthenticationFilter
- RequestCacheAwareFilter
- SecurityContextHolderAwareRequestFilter
- JaasApiIntegrationFilter
- RememberMeAuthenticationFilter
- AnonymousAuthenticationFilter
- OAuth2AuthorizationCodeGrantFilter
- SessionManagementFilter
- ExceptionTranslationFilter
- FilterSecurityInterceptor
- SwitchUserFilter
Spring security의 기본 동작 방식에 대해 쭉 살펴보았는데,
혹시 설명이 잘못되었거나 추가적인 설명을 원하는 부분이 있다면 알려주시면 감사하겠습니다 :)
참고자료
https://yoonbing9.tistory.com/104
https://velog.io/@seongwon97/Spring-Security-Filter%EB%9E%80
'Java Spring > Security' 카테고리의 다른 글
JWT란? JWT 생성과 사용 방법 알아보기 (0) | 2022.08.05 |
---|---|
Authorization(인가)-인가 내부 절차 & 권한 설정하기 (0) | 2022.08.01 |
Authentication(인증) (2) - 로그인 절차 & 코드구현 (0) | 2022.07.30 |
Authentication(인증) (1) - 사용자 정보 저장하기 & 비밀번호 암호화하여 저장하기(DelegatingPasswordEncoder는 무엇인가?) (1) | 2022.07.29 |
Spring Security Framework은 어떤 도구인지 대표적인 기능 알아보기 (0) | 2022.07.25 |