UsernamePasswordAuthenticationFilter
가 해당 요청을 전달받는다.UsernamePasswordAuthenticationFilter
는 Username과 Password를 이용해 UsernamePasswordAuthenticationToken
을 생성해서 Authentication
을 생성한다. 방금 생성된 Authentication
은 아직 인증이 되지 않은 상태이다.UsernamePasswordAuthenticationFilter
가 아직 인증되지 않은 Authentication
을 AuthenticationManager
에게 전달한다.AuthenticationManager
는 인증 처리를 총괄하는 역할을 하는 인터페이스고, AuthenticationManager
를 구현한 클래스가 ProviderManager
이다.ProviderManager
로부터 Authentication
을 전달 받은 AuthenticationProvider
는 UserDetailsService
를 이용해 UserDetails
를 조회한다.UserDetailsService
는 데이터베이스 등의 저장소에서 사용자의 크리덴셜(Credential)을 포함한 사용자의 정보를 조회한다.UserDetails
를 생성한 후, AuthenticationProvider
에게 전달한다.AuthenticationProvider
는 전달받은 UserDetails
를 PasswordEncoder
를 이용해 암호화된 Password와 인증을 위한 Authentication
에 포함된 Password가 일치하는지 검증한다.Authentication
을 생성하고, 실패하면 Exception을 발생시키고 인증 처리를 중단한다.AuthenticationProvider
는 인증된 Authentication
을 ProviderManager
에게 전달한다.Authentication
에는 인증에 성공한 사용자의 정보(Principal, Credential, GrantedAuthorities)를 가지고 있다.ProviderManager
는 인증된 Authentication
을 다시 UsernamePasswordAuthenticationFilter
에게 전달한다.Authentication
을 전달받은 UsernamePasswordAuthenticationFilter
는 마지막으로 SecurityContextHolder
를 이용해 SecurityContext
에 인증된 Authentication
을 저장한다.이 흐름을 자세히 살펴보자면
UsernamePasswordAuthenticationFilter
는 AbstractAuthenticationProcessingFilter
를 상속한다.
UsernamepasswordAuthenticationFilter
에 doFilter()
가 존재하지 않는 이유는 상위 클래스인 AbstractAuthenticationProcessingFilter
클래스가 doFilter()
메서드를 포함하고 있기 때문이다.
결과적으로 로그인 request를 제일 먼저 전달받는 클래스는 AbstractAuthenticationProcessingFilter
클래스이다.
AbstractAuthenticationProcessingFilter
는 HTTP 기반의 인증 요청을 처리하지만 실질적인 인증 시도는 하위 클래스에 맡기고, 인증에 성공하면 인증된 사용자의 정보를 SecurityContext에 저장하는 역할을 한다.
UsernamePasswordAuthenticationToken
은 Spring Security에서 Username/Password로 인증을 수행하기 위해 필요한 토큰이며, 인증 성공 후 인증에 성공한 사용자의 인증 정보가 UsernamePasswordAuthenticationToken
에 포함돼 Authentication
객체 형태로 SecurityContext
에 저장된다.
Authentication
은 Spring Security에서의 인증 자체를 표현하는 인터페이스이다.
애플리케이션의 코드상에서 인증을 위해 생성되는 인증 토큰 또는 인증 성공 후 생성되는 토큰은 UsernamePasswordAuthenticationToken
과 같은 하위 클래스의 형태로 생성되지만 생성된 토큰을 리턴 받거나 SecurityContext
에 저장될 경우에 Authentication
형태로 리턴 받거나 저장된다.
이름 그대로 인증 처리를 총괄하는 매니저 역할을 하는 인터페이스이다.
인증을 위한 Filter는 AuthenticationManager
를 통해 느슨한 결합을 유지하고 있으며, 인증을 위한 실질적인 관리는 AuthenticationMangager
를 구현하는 구현 클래스를 통해 이루어진다.
일반적으로 AuthenticationManager
인터페이스의 구현클래스라고 하면 ProviderManager
를 가리킨다.
AuthenticationProvider
를 관리하고, AuthenticationProvider
에게 인증 처리를 위임하는 역할을 한다.
AuthenticationManager
로부터 인증 처리를 위임받아 실질적인 인증 수행을 담당하는 컴포넌트이다.
Username/Password 기반의 인증 처리는 DaoAuthenticationProvider
가 담당하며, DaoAuthenticationProvider
는 UserDetailsService
로부터 전달받은 UserDetails
를 이용해 인증을 처리한다.
UserDetails
는 데이터베이스 등의 저장소에 저장된 사용자의 Username과 사용자의 자격을 증명해주는 크리덴셜(Credential)인 Password 그리고 사용자의 권한 정보를 포함하는 컴포넌트이며, AuthenticationProvider
는 UserDetails
를 이용해 자격 증명을 수행한다.
UserDetailService
는 UserDetails
를 로드(load)하는 핵심 인터페이스이다.
즉, 사용자의 정보를 메모리에서 로드하든 데이터베이스에서 로드하든 Spring Security가 이해할 수 있는 UserDetails
로 리턴해주기만 하면 된다.
SecurityContext
는 인증된 Authentication
객체를 저장하는 컴포넌트이고, SecurityContextHolder
는 SecurityContext
를 관리하는 역할을 담당한다.
SecurityContext
가 인증된 Authentication
을 포함하고 있고, 이SecurityContext
를 다시SecurityContextHolder
가 포함하고 있다.
SecurityContextHolder
가 SecurityContext
를 포함하고 있는 것은 SecurityContextHolder
를 통해 인증된 Authentication
을 SecurityContext
에 설정할 수 있고 또한 SecurityContextHolder
를 통해 인증된 Authentication
객체에 접근할 수 있다는 것을 의미한다.