스프링 시큐리티 주요 아키텍처 컴포넌트
SecurityContextHolder
SecurityContext
SecurityContextHolder
로 접근할 수 있으며 인증한 사용자의 Authentication
을 가지고 있다.Authentication
SecurityContext
에서 현재 사용자를 제공하기 위한 AuthenticationManager
에 대한 입력이 될 수 있다.GrantedAuthority
Authentication
에서 접근 주체(principal)에 부여한 권한이다.AuthenticationManager
ProviderManager
AuthenticationManager
의 일반적인 구현체AuthenticationProvider
ProverManger
에 의해 사용되어 특정 타입의 인증을 수행AuthenticationEntryPoint
AbstractAuthenticationProcessingFilter
Filter
SecurityContext
를 포함하고 있다.
SecurityContextHolder
에 어떻게 값이 들어갔는지는 상관하지 않고 값이 있다면 인증된 사용자가 있다고 본다.
사용자가 인증되었음을 나타내는 가장 쉬운 방법은 직접 값을 넣는 것이다.
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication =
new TestingAuthenticationToken("username", "password", "ROLE_USER");
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
SecurityContextHolder.getContext.setAuthentication()
을 사용해선 안 된다.Authentication
객체를 생성한다.
UserPasswordAuthenticationToken
을 주로 사용한다.SecurityContexHolder
에 SecurityContext
를 설정한다.인증된 사용자 정보를 얻으려면 SecurityContextHolder
를 통해 접근할 수 있다.
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
String username = authentication.getName();
Object principal = authentication.getPrincipal();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
SecurityContextHolder
는 ThreadLocal
에 정보를 저장하기에 동일 스레드라면 항상 SecurityContext
에 접근할 수 있다.
FilterChainProxy
가 항상 ThreadLocal
을 비워준다.SecurityContext
는 Authentication
객체를 가지고 있다.Authentication
은 다음 2가지 목적으로 제공된다.
AuthenticationManager
의 입력으로 사용되어 인증된 사용자의 credentials을 제공한다.SecurityContext
에서 현재 인증된 Authentication
을 얻을 수 있다.Authentication
은 다음을 포함한다.
principal
: 사용자를 나타내며 username/password로 인증했을 시 UserDetails
인스턴스로 나타난다.credentials
: 주로 패스워드이다. 대부분 유츌되지 않도록 인증한 다음 비운다.authorities
: GratedAuthority
의 추상화로 사용자에게 부여한 권한이다.Authentication.getAuthorities()
로 얻을 수 있다.
GrantedAuthority
의 Collection
이 반환된다.UserDetailsService
가 GrantedAuthority
를 로드한다.Authentication
을 SecurityContextHolder
에 설정하는 건 AuthenticationManager
를 호출한 객체(시큐리티의 필터)가 담당한다.SecurityContextHolder
에 AuthenticationManager
를 거치지 않고 Authentication
을 직접 설정할 수도 있다.AuthenticationManager
의 구현체는 보통 ProviderManager
이다.AuthenticaitonManager
의 구현체ProviderManager
는 동작을 AuthenticaitonProvider
의 List
에 위임한다.
AuthenticationProvider
는 인증을 성공시키거나 실패시킬 수 있다.AuthenticationProvider
에 결정을 맡긴다.AuthenticationProvider
가 인증을 판단하지 못하면 특별한 예외인 ProviderNotFoundException
이 발생한다.
ProviderFoundException
이 발생했다는 뜻은 넘겨진Authentication
유형을 지원하는ProviderManager
가 설정되지 않았다는 것이다.
ProviderManager
는 인증에 성공하면 리턴하는 Authentication
객체에 있는 민감 credential 정보를 지운다.
HttpSession
에 길게 유지하지 않는다.애플리케이션에서 사용자 객체를 캐싱하는 경우
Authentication
이 credential을 지워버린다면 캐시된 값으로는 더 이상 인증할 수 없다. 따라서 캐시를 사용한다면 이를 고려하여 구현해야 한다. 객체의 복사본을 만들거나ProviderManager
의eraseCredentialsAfterAuthentication
프로퍼티를 비활성화시켜도 된다.
ProviderManager
에 여러 AuthenticationProvider
를 주입할 수 있다.
AuthenticationProvider
는 특정 유형의 인증을 수행한다.AuthenticationManager
빈만으로 여러 유형의 인증을 모두 처리할 수 있다.
ProviderManager
가 여러 인증 유형을 지원하는 AuthenticationProvider
들을 가지고 있기에AuthenticationEntryPoint
는 클라이언트에게 credentials을 요청하는 HTTP 응답을 보낼 때 사용한다.
AbstractAuthentiationProcessingFilter
는 사용자 credentials
을 인증하는 base Filter
다.
AuthenticationEntryPoint
가 credential
요청 응답을 보내는 것
1. 사용자가 credential을 제출하면 AbstractAuthenticationProcessingFitler
가 HttpServletRequest
에서 Authentication
을 생성한다.
AbstractAuthenticationProcessingFitler
의 하위 클래스에 따라 다르다.UsernamePasswordAuthenticationFilter
라면 UsernamePasswordAuthenticationToken
타입이 생성된다.
Authentication
은 인증되기 위해 AuthenticationManager
에 전달된다.SecurityContextHolder
가 비워진다.RememberMeServices.loginFial
을 실행하는데 remember me를 설정하지 않았다면 동작하지 않는다.AuthenticationFailureHandler
가 동작한다.
SessionAuthenticationStrategy
가 새로운 로그인을 통지 받는다.SecurityContextHolder
에 Authentication
이 설정되고 SecurityContextPersistenceFilter
가 SecurityContext
를 HttpSession
에 저장한다.RememberMeServices.loginSuccess
가 동작하는데 remember me가 설저오디지 않았다면 동작하지 않는다.ApplicationEventPublisher
가 InteractiveAuthenticationSuccessEvent
를 발행한다.AuthenticationSuccessHandler
가 동작한다.