Spring Security 아키텍처
1. AuthenticationFilter
- Spring MVC 기준으로 요청이 DispatcherServlet에 도달하기 전에 인증 필터가 요청을 가로챔
- 모든 들어오는 요청은 이러한 필터들을 통과하며, 여기서 인증 및 인가가 이루어짐
- 요청의 유형에 따라 BasicAuthenticationFilter, UsernamePasswordAuthenticationFilter 등 다양한 인증 필터 존재
- 요청이 적절한 AuthenticationFilter에 의해 가로채지면, 필터는 요청에서 username과 password를 추출하여 Authentication 객체 생성
- 추출된 자격 증명이 username과 password일 경우, 위 사진처럼 UsernamePasswordAuthenticationToken 생성
2. AuthenticationManager
- AuthenticationFilter는 생성한 Authentication 객체를 사용하여 AuthenticationManager의 authenticate 메서드 호출
- Authentication Manager는 인터페이스일 뿐이며, authenticate 메서드의 실제 구현은 구현체인 ProviderManager가 제공
- 중요한 점은 Authentication Manager가 Authentication 객체를 입력으로 받아, 인증 성공 시 다시 Authentication 타입의 객체를 반환
- ProviderManager는 AuthenticationProvider의 목록을 가지고 있음
- ProviderManager의 authenticate 메서드는 적절한 AuthenticationProvider의 authenticate 메서드를 호출
- 인증 성공 시, ProviderManager는 Principal Authentication 객체를 반환
3. AuthenticationProvider
- AuthenticationProvider는 단일 authenticate 메서드를 가진 인터페이스
- AuthenticationManager는 HTTP 필터 계층에서 요청을 수신하고 해당 책임을 AuthenticationProvider에게 위임
- CasAuthenticationProvider, DaoAuthenticationProvider 등과 같은 다양한 구현체들이 존재하며 상황에 따라 적절한 AuthenticationProvider 구현체가 사용됨
- AuthenticationProvider 구현체의 authenticate 메서드가 호출될 때 실제 인증이 이루어짐
- AuthenticationProvider는 UserDetailsService를 사용하여 username에 해당하는 User 객체를 데이터베이스 혹은 인메모리에서 불러옴
- User 객체의 자격 증명과 AuthenticationFilter에서 생성한 Authentication 객체의 자격 증명과 비교
- password가 인코딩되어 있을 경우 Authentication 객체의 password를 PasswordEncoder를 통해 인코딩 후 비교
- 인증 성공 시 Principal Authentication 객체를 반환하며 인증된 엔티티에 대한 세부 정보가 SecurityContext에 저장되어 인증 데이터를 유지
4. UserDetailsService
- loadUserByUsername이라는 단일 메서드를 가진 인터페이스
- CachingUserDetailsService, JDBCDaoImpl 등과 같이 다양한 구현체들이 존재하며 상황에 따라 적절한 UserDetailsService가 호출됨
- UserDetailsService는 username과 password에 해당하는 User 객체를 가져오는 역할을 수행하며 해당 User 객체는 Authentication 객체의 username과 password가 일치하는지 검증하는 역할
- username을 통해 사용자를 검색 (READ)
- READ를 제외한 CREATE, UPDATE, DELETE는 UserDetailsManager가 수행
- UserDetailsManager가 UserDetailService를 상속하고 있기 때문에 클라이언트는 UserDetailsManager 구현체를 정의할 때 CRUD를 모두 재정의하면 됨
5. UserDetails
- UserDetails 인터페이스를 기반으로 Spring Security에서는 사용자를 표현
- 인터페이스이기 때문에 애플리케이션 수준에서 UserDetails를 구현해야 함
- 총 7개의 메서드가 존재하며 비활성화 관련 메서드는 default 메서드로 선언되어 있어 재정의하지 않을 경우 기본적으로 true를 반환하여 사용자가 항상 활성화되어 있음
- getAuthorities(): 애플리케이션 사용자가 수행할 수 있는 작업을 GrantedAuthority 인스턴스의 컬렉션으로 반환
- getPassword(): 사용자의 암호 반환
- getUsername(): 사용자의 사용자 ID 반환
- isAccountNonExpired(): 계정 만료 여부
- isAccountNonLocked(): 계정 잠금 여부
- isCredentialsNonExpired(): 자격 증명 만료 여부
- isEnabled(): 계정 활성화 여부
비고
1. GrantedAuthority
- 사용자는 사용자가 수행할 수 있는 작업을 나타내는 이용 권리의 집합을 가지며 이를 보통 권한이라고 표현
- 사용자는 하나 이상의 권한을 가질 수 있으며 GrantedAuthority라는 인터페이스를 통해 이를 구현할 수 있음
- UserDetailsService는 username으로 조회한 사용자 세부 정보인 UserDetails를 반환하며 반환된 사용자는 하나 이상의 권한을 가질 수 있으며 이를 GrantedAuthority로 구현 가능
2. PasswordEncoder
- 비밀번호를 저장할 때 보통 암호화를 하며 이를 위해서는 Spring Security의 PasswordEncoder를 활용
- PasswordEncoder 인터페이스를 통해 Spring Security에서 사용자 암호를 검증
- 인증 프로세스에서 암호가 유효한지 확인하는 과정을 거침 (matches)
- 암호에 대한 인코딩을 수행 (encode)
* upgradeEncoding 메서드는 기본적으로 false를 반환하지만 true를 반환하도록 재정의 시 보안 향상을 위해 인코딩 된 암호를 재인코딩
3. AuthenticationManager
- 인증 요청을 허용하거나 거부하기 위해 AuthenticationManager와 AuthenticationProvider는 서로 연결되어 있음
- AuthenticationManager가 중앙에서 사용자의 접근을 허용할지 거불할지 판단하는 컨트롤 파워
- AuthenticationManager는 AuthenticationProvider에게 인증 작업을 위임하여 이를 판단
- AuthenticationManager는 사용 가능한 AuthenticationProvider 중 하나에 인증을 위임
- AuthenticationProvider는 주어진 인증 유형을 지원하지 않거나 객체 유형은 지원하지만 해당 특정 객체를 인증하는 방법을 모를 가능성 존재
- 인증을 평가한 후 요처이 올바른지 판단할 수 있는 AuthenticationProvider가 AuthenticationManager에 응답
4. Authentication & Principal
- Spring Security에서의 Authencation은 인증 프로세스의 필수 인터페이스이며 인증 요청 이벤트를 나타나며 애플리케이션에 접근을 요청한 엔티티의 세부 정보를 담고 있음
- Principal은 애플리케이션에서 접근을 요청하는 사용자 혹은 주체
- Authentication 인터페이스는 Principal 인터페이스를 상속
- 앞서 설명한 AuthenticationProvider 인터페이스의 기본 구현은
- 사용자를 찾는 UserDetailsService에 위임
- PasswordEncoder로 인증 프로세스에서 암호를 관리
- Authentication 인터페이스와 강결합되어 있음
5. SecurityContext
- AuthenticationManager가 인증 프로세스를 성공적으로 완료한 후 요청이 유지되는 동안 Authentication 인스턴스가 저장되는 위치
- Controller가 SecurityContext에 있는 세부 정보를 이용할 수 있음
- SecurityContext는 세 가지 전략에 의해 관리되며 관리자 역할을 하는 객체를 SecurityContextHolder라고 함
- MODE_THREADLOCAL (기본 전략)
- MODE_INHERITABLETHREADLOCAL
- MODE_GLOBAL
5.1 MODE_THREADLOCAL
- 각 쓰레드가 SecurityContext에 각자의 세부 정보를 저장할 수 있도로 지원
- Spring MVC는 request-per-thread 모델이기 때문에 각 요청이 개별 쓰레드를 가짐
5.2 MODE_INHERITABLETHREADLOCAL
- parallel stream과 같은 미동기 메서드의 경우 SecurityContext를 다음 쓰레드로 복사하도록 Spring Security에서 알려줌
- 해당 방식을 사용하면 @Async 메서드를 실행하는 새로운 쓰레드가 SecurityContext를 상속할 수 있음
5.3 MODE_GLOBAL
- 애플리케이션의 모든 쓰레드가 같은 SecurityContext를 참조
참고
https://www.javainuse.com/webseries/spring-security-jwt/chap3
반응형
'Spring > Spring Security' 카테고리의 다른 글
[Spring Security] 필터 체인과 커스텀 필터 (0) | 2024.10.08 |
---|---|
[Spring Security] 액세스 제한과 권한 (0) | 2024.10.07 |
[Spring Security] OAuth 2.0 개요 (0) | 2023.12.21 |
[Spring Security] Remember-me를 통해 로그인 유지하기 (0) | 2022.03.27 |
[Spring Security] @AuthenticationPrincipal (0) | 2022.03.26 |