Spring Security - 2
Spring Security - 2
Spring Security에 대해 공부하고 정리한 내용입니다.
Authentication
Authentication은 Spring Security에서 두가지 목적을 갖고있다.
AuthenticationManager의 입력으로 한 유저가 인증하기위해 제공한 credentials을 제공하기위함. 이 경우isAuthenticated()의 결과는 false다.- 현재 인증된 사용자를 나타낸다. 현재
Authentication이 SecurityContext로 부터 얻을 수 있다면 인증된 사용자라고 나타낼 수 있다.
Authentication은 다음을 포함하고 있다.
- principal - 유저를 식별한다. 유저 이름과 패스워드와 함께 인증이 시도 될 때, principal은 보통
UserDetails의 인스턴스이다. - credentials - 보통 패스워드를 나타낸다. 유저가 인증된 이후에는 노출이 되지 않도록 제거된다.
- authorities -
GrantedAuthority는 유저가 권한이 있다는 높은 레벨의 허가를 나타낸다. 예를 들어 roles or scopes를 얘기한다.
GrantedAuthority
위에 Authentication에서 보았듯이 GrantedAuthority는 유저가 권한이 있다는 높은 레벨의 허가를 나타낸다.
GrantedAuthority는 Authetication.getAuthorities 메소드를 통해 얻을 수 있다. 이 메소드는 GrantedAuthority의 컬렉션을 제공한다.
AuthenticationManager
AuthenticationManager는 Spring Security 필터가 인증을 수행하는 방법을 정의한 API다. 반환 된 Authentication은 AuthenticationManager를 실행한 컨트롤러(Spring Security 필터들)에 의해 SecurityContextHolder에 설정이된다.
AuthenticationManager를 사용하지 않고 Spring Security 필터에서 말고 직접 Authentication을 SecurityContextHolder에 설정할 수 있다.
가장 일반적인 AuthenticationManager의 구현체는 ProviderManager 이다.
ProviderManager
ProviderManager 가장 일반적인 AuthenticationManager의 구현체이다.

ProviderManager 동작
ProviderManager는 AuthenticationProvider 리스트로 위임을 한다. 각각의 AuthenticationProvider는 인증이 성공, 실패를 나타낼 수 있고 결정할 수 없으면 다음 AuthenticationProvider에게 결정하도록 내려보낸다. 만약 어떠한 AuthenticationProvider가 인증을 할 수 없으면 AuthenticationException의 ProviderNotFoundException와 함께 인증 실패를 알릴 것이다.
여기서 결정할 수 없다는 것은 각 AuthenticationProvider는 특정 유형의 인증을 수행하는 방법을 갖고 있고 이에 맞지 않다는 것을 얘기한다. 예를 들어 한 AuthenticationProvider는 유저 이름과 패스워드로 검증을 할 수 있는 반면, 다른 AuthenticationProvider는 다른 방식으로 검증을 한다. 즉, 다양한 인증 방식을 지원하면서 그 중 하나의 방식으로 인증을 할 수 있다.
AuthenticationProvider
위에서 보았듯이 다수의 AuthenticationProvider들은 ProviderManger에 속해 있고 각각의 AuthenticationProvider는 특정 유형의 인증을 수행한다.
예를 들어 DaoAuthenticationProvider는 유저 이름과 패스워드로 인증을 지원하고 반면에 JwtAuthenticationProvider는 JWT 토큰으로 인증을 지원한다.
Request Credential with AuthenticationEntryPoint
AuthenticationEntryPoint는 유저에게 credential을 요청하는 HTTP 응답을 보내는 것에 사용된다.
인증할 수 있는 정보를 클라이언트가 같이 보낸다면 HTTP 응답으로 crendential 요청을 할 필요가 없지만 클라이언트가 인증되지 않은 상태로 자원을 요청한다면 접근을 인가할 수 없다. 이 경우에 AuthenticationEntryPoint를 구현함으로 클라이언트에게 credential을 요청하는 것이다. AuthenticationEntryPoint에 page를 redirect하거나 WWW-Authenticate를 응답 헤더에 포함하는 방법 등으로 클라이언트에게 요청을 한다.
AbstractAuthenticationProcessingFilter
유저의 credential을 인증하기 위한 기반 필터이다.

ProviderManager 동작
유저가 credential을 보냈을 때
AbstractAuthenticationProcessingFilter가 인증 될HttpServletRequest에Authentication을 만든다.Authentication의 타입은AbstractAuthenticationProcessingFilter의 subclass의 의존해서 만들어진다.예를 들어,
UsernamePasswordAuthenticationFilter는HttpServletRequest에 제출된 유저이름과 패스워드로UsernamePaswordAuthenticationToken을 만든다.AuthenticationManager에게 인증을 위해Authentication이 전달된다.만약 인증이 실패라면 인증 실패 처리가 된다.
SecurityContextHolder는 비워진다.RememberMeService.loginFail이 실행된다. Remember me가 설정되지 않았다면 아무것도 하지 않는다.AuthneticationFailureHandler가 실행된다.
만약 인증이 성공이라면 인증 성공 처리가 된다.
SessionAuthenticationStrategy에 새 로그인이 알려진다.Authentication이SecurityContextHolder에 설정되고 이후에SecurityContextPersistencFilter가SecurityContext를HttpSession에 저장한다.RememberMeService.loginSuccess가 실행된다. Remember me가 설정되지 않았다면 아무것도 하지 않는다.ApplicationEventPublisher는InteractiveAuthenticationSuccessEvent를 발행한다.AuthenticationSuccessHandler가 실행된다.