이 글은 정수원님의 Infrean 강의를 학습한 내용을 정리하여 작성합니다.
스프링 시큐리티 필터 및 아키텍처 정리
- 그림의 윗부분은 시큐리티의 초기화 과정에 해당한다.
- 그림의 아래부분은 각 필터들의 처리 과정에 해당한다.
스프링 시큐리티 초기화
- SecurityConfig 설정 클래스를 생성한다.
- 내부에 여러 API를 정의한다.
- 각 API들은 요청을 받아 처리한다.
- 시큐리티 초기화 시 설정한 API와 구성대로 Filter들을 생성한다.
- 이때, HttpSecurity 클래스가 필터들을 생성한다.
- 생성된 필터들은 WebSecurity 클래스에게 전달된다.
- WebSecurity는 FilterChainProxy의 Bean 객체를 생성한다.
- 이때 생성자로 필터들을 전달한다.
- FilterChainProxy는 SecurityConfig 설정 파일에 따른 각각의 필터 목록들을 가지게 된다.
- 서블릿 필터인 DelgatingFilterProxy는 springSecurityFilterChain 이라는 이름을 가진 Bean 클래스를 찾는다.
- DelegatingFilterProxy는 사용자의 요청을 springSecurityFilterChain에게 전달하는 역할을 수행한다.
스프링 시큐리티 필터
사용자가 인증을 시도하는 경우
- 사용자가 인증을 시도하면 DelegatingFilterProxy가 가장 먼저 요청을 받는다.
- DelegatingFilterProxy는 FilterChainProxy에게 요청을 위임한다.
- FilterChainProxy는 초기화에서 생성된 필터들의 목록을 가진다.
- FilterChainProxy는 사용자 요청을 처리하기 위해 자신이 가진 각각의 필터들을 호출한다.
- 그림의 좌측에서 우측으로 순서대로 수행된다.
- SecurityContextPersistenceFilter
- 내부적으로 HttpSessionSecurityContextRepository 클래스를 가진다.
- HttpSessionSecurityContextRepository 클래스는 SecurityContext 객체를 생성한다.
- loadContext를 통해 요청을 수행한 사용자가 이전에 SecurityContext 객체를 생성해 Session에 저장한 이력이 있는지 검사한다.
- 저장된 적이 없다면 CreateSecurityContext를 통해 새로운 SecurityContext 객체를 생성하고 SecurityContextHolder 내부에 저장한다.
(처음 인증을 요청하는 사용자 혹은 익명사용자) - 이러한 과정이 모두 끝나면 다음 필터인 LogoutFilter로 이동한다.
- 내부적으로 HttpSessionSecurityContextRepository 클래스를 가진다.
- LogoutFilter
- LogoutFilter는 로그아웃을 수행하는 필터이다.
- 현재는 인증 요청을 수행하고 있으므로 LogoutFilter를 건너뛴다.
- UsernamePasswordAuthenticationFilter
- 실제 Form 인증 처리를 수행하는 필터이다.
- 인증 객체(Authentication)를 생성해 ID와 Password를 저장한다.
- 인증 관리자 (AuthenticationManager)에게 인증 처리를 맡긴다.
- 인증 관리자는 AuthenticationProvider (실질적으로 검증 단계를 총괄)에게 인증 처리를 위임한다.
- 최종적으로 인증에 성공한 경우 인증에 성공한 결과를 담은 Authentication 객체를 생성한 뒤 SecurityContextHolder 내부 SecurityContext 객체 내부에저장한다.
- SessionManagementFilter
- 인증 성공 후 후속처리를 수행한다.
- ConcurrentSession을 통해 동시 접근을 체크한다.
- 사용자 인증 성공 후 세션이 새롭게 생성된 시점에 인증 이전 쿠키는 삭제되고 새로운 쿠키가 발급되도록 SessionFixation 기능이 동작한다.
- Register SessionInfo에 사용자 세션 정보가 저장된다.
- 최종적으로 인증 성공 후 일반적으로 SuccessHandler에서 다음 페이지로 리다이렉트한다.
- 이때 SecurityContextPersistenceFilter가 세션에 최종적으로 인증에 성공한 Authenticaiton 객체를 저장하는 역할을 응답 직전에 수행한다.
- 그리고 SecurityContext를 비우게 된다.
사용자 인증 후 자원에 접근하는 경우
- 인증 후 리다이렉트를 통해 루트 페이지로 이동하고자 하는 경우 DelegatingFilterProxy가 그 요청을 받는다.
- DelegatingFilterProxy는 FilterChainProxy에게 요청을 위임한다.
- FilterChainProxy는 자신이 가진 필터들에게 순서대로 요청을 위임한다.
- SecurityContextPersistenceFilter는 요청을 받아 loadContext를 수행해 요청한 사용자가 세션에 SecurityContext를 저장한 적 있는지 여부를 검사한다.
- 이전에 세션에 인증 객체를 저장한 적이 있으므로 꺼내온다.
- 그 뒤 SecurityContextHolder에 저장한다.
- 다음 필터를 호출한다.
- LogoutFilter와 UsernamePasswordAuthenticationFilter를 건너뛰고 ConcurrentSessionFilter를 호출한다.
- ConcurrentSessionFilter 검사를 통과하면 RememberMeAuthenticationFilter를 호출하는데 인증 받은 사용자가 요청하면 아무런 작업도 수행하지 않는다.
- AnonymousAuthenticationFilter는 어느 인증과 권한없이 특정 자원을 요청하는 경우 동작한다.
- SessionManagementFilter는 현재 세션에 SecurityContext가 없는 경우 또는 세션이 만료되어 Null인 경우 동작한다.
- ExceptionTranslationFilter는 인증 또는 인가 예외가 발생하는 경우 동작한다.
- Try
chain doFilter
catch
- Try
- FilterSecurityInterceptor에서 발생하는 예외는 모두 ExceptionTranslationFilter로 보내진다.
- 인가 처리를 수행한다.
- 현재 접속한 사용자가 SecurityContext 내부에 Authenticaiton 객체를 가지고 있는지 여부를 확인한다.
- 존재하지 않으면 인증 예외를 발생시킨다.
- 인증이 되지 않으면 인가 처리는 불가능하다.
- 인가 처리는 인증 객체를 활용해야 한다.
- 사용자가 인증 객체를 가지고 있으면 인가 처리를 수행하는데 AccessDecisionManager가 동작한다.
- 내부적으로 AccessDecisionVoter를 통해 자원 접근 승인 여부를 결정한다.
- 권한이 없을 경우 인가 예외를 발생시킨다.
'스프링 시큐리티 > 스프링 시큐리티 주요 아키텍처 이해' 카테고리의 다른 글
인가 결정 심의자 - AccessDecisionManager, AccessDecisionVoter (0) | 2023.02.10 |
---|---|
인가 개념 및 필터 이해: Authorization, FilterSecurityInterceptor (0) | 2023.02.10 |
인증 처리자 - AuthenticationProvider (0) | 2023.02.08 |
인증 관리자: AuthenticationManager (0) | 2023.02.08 |
인증 흐름 이해 - AuthenticationFlow (0) | 2023.01.31 |