Spring Security Architecture
- Spring Security Architecture 를 그림으로 나타내면 아래와 같다.
- 요청이 들어오면 서블릿 필터중에
DeligationFilterProxy
라는 필터가 FilterChainProxy를SecurityFilterAutoConfiguration
이라는 이름의 빈으로 등록 한다. - FilterChainProxy 는 요청에 따라 적합한 필터들이 체인형태로 구성된 SecurityFilterChain 을 사용한다. -> 이는 WebSecurity 에 의해서 만들어진다.
- 이러한 필터들이 사용하는 객체들이 있는다.
- 인증 -> AuthenticationManager
- 인가 -> AccessDecisionManager
- AuthenticationManager
- 보통 구현체인 ProviderManager 를 많이 사용한다.
- ProviderManager 는 여러 AuthenticationProvider 를 사용하는데 그 중에서 하나가 DaoAuthenticationProvider 이다.
- DaoAuthenticationProvider 는 UserDetailsService라는 Dao 인터페이스를 사용해서 인증을 처리한다.
- 여기서 인증이 성공한다면 그 정보를 SecurityContextHolder 에 넣어서 애플리케이션 전반에 걸처 사용한다.
- 이렇게 만들어진 정보는 SecurityContextPersistenceFilter 에 의해 사용된다.
- AccessDecisionManager
- FilterSecurityInterceptor는 인가를 처리하기 위해서 AccessDecisionManager를 사용한다.
- AccessDecisionManager가 인가를 처리하는 방법은 3가지가 있는데 그 중에서 하나가 AffirmativeBased 이다.
- AffirmativeBased 는 AccessDecisionVoter 중에서 WebExpressionVoter 만을 사용한다.
- WebExpressionVoter 는 SecurityExpressionHandler 를 이용해서 Exception을 처리하는데 계층형한 권한 처리를 위해서 SecurityExpressionHandler 를 커스터 마이징 할 수 있다.
- 먼저 초기화 과정에서 SecurityConfig 설정파일들에서 정의한 api 들을 바탕으로 filters 을 생성한다.
- WebSecurity 는 filters 들을 전달받고, filters 를 생성자의 인자로 FilterChainProxy 빈을 springSecurityChain 이라는 이름으로 생성한다.
- Servlet Filter 중 하나인 DelegatingFilterProxy 는 초기화 될때, springSecurityChain 이름으로 빈을 찾는데 그것이 FilterChainProxy 이다.
- DelegatingFilterProxy 는 FilterChainProxy 에게 요청을 위임한다.
- 여기까지가 초기화 과정이고, 이후로 인증과 인가에 관련된 사용자의 요청이 전달된다.
- 사용자의 최초 인증 (폼 인증)
- SecurityContextPersistenceFilter -> UsernamePasswordAuthenticationFilter -> SessionManagementFilter
- 로그인하고 리소스 접근
- SecurityContextPersistenceFilter -> ExceptionTranslationFilter -> FilterSecurityInterceptor
- SecurityContextPersistenceFilter -> ExceptionTranslationFilter -> FilterSecurityInterceptor
Authentication Flow
- 먼저 클라이언트가 폼 인증을 요청한다.
- UsernamePasswordAuthenticationFilter 는 사용자의 요청을 받아서 아이디와 패스워드를 저장할 수 있는 Authentication 을 생성하고 AuthenticationManager에게 인증처리를 맡긴다.
- AuthenticationManager 는 인증의 전반적인 관리하지만 실제로 인증역할을 하지 않고 AuthenticationProvider에 위임한다.
- AuthenticationProvider 는 UserDeatilsService 의 loadUserByUsername 메소드에 username(userId) 를 넘기면서, UserDeatilsService 에게 User 객체를 요구한다.
- UserDetailsService 는 유저 객체를 DB 에서 조회해서 UserDetails 타입으로 반환해 준다.
- DB 에 존재하지 않는다면 UserNameNotFoundException이 호출되어 예외가 발생한다.
- AuthenticationProvider 는 UserDetailsService 에게 받은 UserDetails 값의 Id, Password 값을 비교해서 인증이 성공한다면 Authentication (UserDetails + Authorities) 객체를 생성하고, AuthenticationManager 에게 전달한다.
- 최종적으로 인증결과를 담은 Authentication 는 다시 UsernamePasswordAuthenticationFilter에게 전달하고 SecurirtyContext에 저장한다.
Authorization
- Authorization 는 무엇이 허가 되었는지를 증명하는 것이다.
- 아래의 그림처럼 인증이 된 후 인가를 처리한다.
- 스프링 시큐리티가 지원하는 권한계층은 아래와 같다.
- 위와 같이 웹, 서비스, 도메인 계층에서 권한을 검증 할 수 있다.
REFERENCES
- 백기선님의 스프링 시큐리티
- 정수원님의 스프링 시큐리티
'Spring Security' 카테고리의 다른 글
CustomAuthenticationProvider (0) | 2022.02.28 |
---|---|
AuthenticationManager 와 AuthenticationProvider (0) | 2022.02.28 |
Security Config (0) | 2022.02.28 |
SecurityContextHolder 와 FilterChainProxy (0) | 2022.02.28 |
SecurityContextHolder, AuthenticationManager, ThreadLocal (0) | 2022.02.28 |