• 사용자가 로그인 폼을 이용한 Request(Username, Password 포함)를 Spring Security가 적용된 애플리케이션에 전송
• 여러 Filter 중에서 UsernamePasswordAuthenticationFilter가 요청을 전달 받음
• UsernamePasswordAuthenticationFilter가 Username, Password를 이용해 UsernamePasswordAuthenticationToken을 생성
( UsernamePasswordAuthenticationToken은 Authentication 인터페이스를 구현한 클래스 )
• UsernamePasswordAuthenticationFilter는 아직 인증되지 않은 Authentication을 AuthenticationManager에게 전달
( AuthenticationManager는 인증 처리를 총괄하는 매니저 역할을 하는 인터페이스, 이를 구현한 클래스가 ProviderManager )
• ProviderManager로부터 Authentication을 전달받은 AuthenticationProvider는 UserDetailsService를 이용해 UserDetails를 조회
(UserDetails는 데이터베이스에 저장된 사용자의 Username과 사용자의 자격을 증명하는 Password(Credential), 그리고 사용자의 권한 정보를 포함하고 있는 컴포넌트, UserDetailsService가 이 UserDetails를 제공)
• UserDetailsService는 데이터베이스에서 사용자의 Credential을 포함한 정보를 조회
• 조회한 정보를 기반으로, UserDetails를 생성하고 AuthenticationProvider에게 전달
• AuthenticationProvider는 PasswordEncoder를 이용해 전달받은 UserDetails에 포함된 암호화된 Password와 인증을 위한 Authentication 안에 포함된 Password가 일치하는지 검증
( 검증에 성공 → UserDetails를 이용해 인증된 Authentication을 생성
검증에 실패 → Exception 발생시키고 인증 처리 중단 )
• AuthenticationProvider는 인증된 Authentication을 ProviderManager에게 전달
( (2)에서의 Authentication은 인증을 위해 필요한 사용자의 로그인 정보를 가짐
(10)에서의 Authentication은 인증에 성공한 사용자의 정보(Principal, Credential, GrantedAuthorities)를 가짐 )
• ProviderManager는 인증된 Authentication을 다시 UsernamePasswordAuthenticationFilter에게 전달
• UsernamePasswordAuthenticationFilter는 SecurityContextHolder를 이용해 SecurityContext에 인증된 Authentication을 저장
( SecurityContext는 Spring Security의 세션 정책에 따라, HttpSession에 저장되어 사용자의 인증 상태를 유지하거나 HttpSession을 생성하지 않고 무상태를 유지)
Spring Security의 인증 처리 흐름에 대해
- https://docs.spring.io/spring-security/reference/servlet/authentication/architecture.html
UsernamePasswordAuthenticationFilter
• Spring Security가 인증 프로세스에서 이용할 수 있도록 UsernamePasswordAuthenticationToken 생성
• AbstractAuthenticationProcessingFilter를 상속
사용자의 로그인 Request를 제일 먼저 만나는 컴포넌트로, 로그인 폼에서 제출되는 Username과 Password를 통한 인증을 처리하는 Filter
AbstractAuthenticationProcessingFilter
• UsernamePasswordAuthenticationFilter가 상속하는 상위 클래스로, Spring Security에서 제공하는 Filter 중 하나
HTTP 기반의 인증 요청을 처리하지만, 실질적인 인증 시도는 하위 클래스에 맡기고, 인증에 성공하면 인증된 사용자의 정보를 SecurityContext에 저장하는 역할
AbstractAuthenticationProcessingFilter에 대해
UsernamePasswordAuthenticationToken
• Spring Security에서 Username과 Password로 인증을 수행하기 위해 필요한 토큰
인증에 성공한 사용자의 정보가 이 토큰에 포함되어 Authentication 객체 형태로 SecurityContext에 저장
Authentication
• Authentication를 구현하는 클래스에서 가지는 정보들 - Principal, Credentials, Authorities
• Principal - 사용자를 식별하는 고유 정보, Username/Password 기반 인증에서는 Username이 Principal이고, 다른 인증 방식에서는 UserDetails가 Principal
• Credentials - 사용자 인증에 필요한 Password를 의미, 인증 직후에 ProvideManager가 해당 Credentials를 삭제
• Authorities - AuthenticationProvider에 의해 부여된 사용자의 접근 권한 목록
(일반적으로 GrantedAuthority 인터페이스의 구현 클래스는 SimpleGrantedAuthority)
Spring Security에서의 인증 자체를 표현하는 인터페이스로, Authentication 객체 형태로 생성된 토큰을 리턴 받거나 SecurityContext에 저장됨
AuthenticationManager
• 인증을 위한 Filter는 AuthenticationManager를 통해, 느슨한 결합을 유지
• 인증을 위한 실질적인 관리는 이 인터페이스를 구현하는 클래스를 통해 이루어짐
인증 처리를 총괄하는 매니저 역할을 하는 인터페이스
ProviderManager
• AuthenticationManager 인터페이스를 구현하는 클래스라고 하면 일반적으로 ProviderManager를 의미
AuthenticationProvider를 관리하고, AuthenticationProvider에게 인증 처리를 위임하는 역할
ProviderManager에 대해
AuthenticationProvider
• AuthenticationManager로부터 인증 처리를 위임 받아 실질적인 인증 수행을 담당하는 컴포넌트
• Username/Password 기반의 인증 처리는 DaoAuthenticationProvider가 담당
( DaoAuthenticationProvider는 UserDetailsService로부터 전달받은 UserDetails를 이용해 인증을 처리 )
AuthenticationProvider 인터페이스의 구현 클래스는 AbstractDetailsAuthenticationProvider이고, DaoAuthenticationProvider는 AbstractUserDetailsAuthenticationProvider를 상속한 확장 클래스
AuthenticationProvider에 대해
UserDetails
• AuthenticationProvider는 UserDetails를 이용해 자격 증명을 수행
데이터베이스 등의 저장소에 저장된 사용자의 Username과 Password(Credential), 그리고 사용자의 권한 정보를 포함하는 컴포넌트
UserDetailsService
• UserDetails를 로드(load)하는 핵심 인터페이스
사용자의 정보를 메모리, 데이터베이스 어디에서 로드하든, Spring Security가 이해할 수 있는 UserDetails로 리턴해주기만 하면 됨
SecurityContext와 SecurityContextHolder
• SecurityContext는 인증된 Authentication 객체를 저장하는 컴포넌트
• SecurityContextHolder는 SecurityContext를 관리하는 역할
Spring Security 입장에서, SecurityContextHolder에 의해 SecurityContext에 값이 채워져있으면 인증된 사용자로 간주
• SecurityContext가 인증된 Authentication을 포함, SecurityContext를 다시 SecurityContextHolder가 포함
SecurityContextHolder가 SecurityContext를 포함
→ SecurityContextHolder를 통해 인증된 Authentication을 SecurityContext에 설정할 수 있음
→ SecurityContextHolder를 통해 인증된 Authentication 객체에 접근할 수 있음
• SecurityContextHolder 기본 전략은 ThreadLocalSecurityContextHolderStrategy
( 현재 실행 쓰레드에 SecurityContext를 연결하기 위해, ThreadLocal을 사용하는 전략 )
( ThreadLocal은 쓰레드 간에 공유되지 않은 쓰레드 고유의 로컬 변수같은 영역을 의미 )
SecurityContextHolder에 대해
ThreadLocal에 대해
- https://www.baeldung.com/java-threadlocal
- https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/ThreadLocal.html
'Develop > Spring' 카테고리의 다른 글
Spring Security에서 지원하는 표현식(Spring EL) (0) | 2022.11.22 |
---|---|
Spring Security 권한 부여 처리 흐름 (0) | 2022.11.22 |
Spring Security 웹 요청 흐름 (0) | 2022.11.19 |
Spring Security - 기본 (0) | 2022.11.19 |
인증/보안 기초 (1) | 2022.11.17 |