2부 스프링 시큐리티: 아키텍처
#
10. SecurityContextHolder와 AuthenticationSecurityContextHolder
- SecurityContext 제공, 기본적으로 ThreadLocal을 사용한다.
SecuuryContext
- Authentication 제공.
Authentication
- Principal과 GrantAuthority 제공.
Principal
- "누구"에 해당하는 정보.
- UserDetailsService에서 리턴한 그 객체.
- 객체는 UserDetails 타입.
GrantAuthority:
- "ROLE_USER", "ROLE_ADMIN"등 Principal이 가지고 있는 "권한"을 나타낸다.
- 인증이후,인가및권한확인할때이정보를참조한다.
UserDetails
- 애플리케이션이 가지고 있는 유저 정보와 스프링 시큐리티가 사용하는 Authentication
UserDetailsService
- 유저 정보를 UserDetails 타입으로 가져오는 DAO (Data Access Object) 인터페이스.
객체 사이의 어댑터
- 구현은 마음대로! (우리는 스프링 데이터 JPA를 사용했습니다.)
#
11. AuthenticationManager와 Authentication스프링 시큐리티에서 인증(Authentication)은 AuthenticationManager가 한다.
- 인자로 받은 Authentication이 유효한 인증인지 확인하고 Authentication 객체를 리턴합니다.
- 인증을 확인하는 과정에서 비활성 계정, 잘못된 비번 , 잠긴 계정 등의 에러를 던질 수 있다.
인즈로 받은 Authentication
- 사용자가 입력한 인증에 필요한 정보(username, password)로 만든 객체. (폼 인증인 경우)
- Authentication
- Principal: “keesun”
- Credentials: “123”
유효한 인증인지 확인
- 사용자가 입력한 password가 UserDetailsService를 통해 읽어온 UserDetails 객체에 들어있는 password와 일치하는지 확인
- 해당 사용자 계정이 잠겨 있진 않은지, 비활성 계정은 아닌지 등 확인
Authentication 객체를 리턴
- Authentication
- Principal: UserDetailsService에서 리턴한 그 객체 (User)
- Credentials:
- GrantedAuthorities
#
12. ThreadLocalJava.lang 패키지에서 제공하는 쓰레드 범위 변수. 즉, 쓰레드 수준의 데이터 저장소.
- 같은 쓰레드 내에서만 공유.
- 따라서 같은 쓰레드라면 해당 데이터를 메소드 매개변수로 넘겨줄 필요 없음.
- SecurityContextHolder의 기본 전략.
#
13. Authencation과 SecurityContextHodlerAuthenticationManager가 인증을 마친 뒤 리턴 받은 Authentication 객체의 행방은?
UsernamePasswordAuthenticationFilter
- 폼 인증을 처리하는 시큐리티 필터
- 인증된 Authentication 객체를 SecurityContextHolder에 넣어주는 필터
- SecurityContextHolder.getContext().setAuthentication(authentication)
SecurityContextPersisenceFilter
- SecurityContext를 HTTP session에 캐시(기본 전략)하여 여러 요청에서 Authentication을 공유할 수 있 공유하는 필터.
- SecurityContextRepository를 교체하여 세션을 HTTP session이 아닌 다른 곳에 저장하는 것도 가능하다.
#
14. 스프링 시큐리티 Filter와 FilterChainProxy스프링 시큐리티가 제공하는 필터들
- WebAsyncManagerIntergrationFilter
- SecurityContextPersistenceFilter
- HeaderWriterFilter
- CsrfFilter
- LogoutFilter
- UsernamePasswordAuthenticationFilter
- DefaultLoginPageGeneratingFilter
- DefaultLogoutPageGeneratingFilter
- BasicAuthenticationFilter
- RequestCacheAwareFtiler
- SecurityContextHolderAwareReqeustFilter
- AnonymouseAuthenticationFilter
- SessionManagementFilter
- ExeptionTranslationFilter
- FilterSecurityInterceptor
이 모든 필터는 FilterChainProxy가 호출합니다.
#
15. DelegatingFilterProxy와 FilterChainProxyDelegatingFilterProxy
- 일반적인 서블릿 필터.
- 서블릿 필터 처리를 스프링에 들어있는 빈으로 위임하고 싶을 때 사용하는 서블릿 필터.
- 타겟 빈 이름을 설정합니다.
- 스프링 부트 없이 스프링 시큐리티 설정할 때는 AbstractSecurityWebApplicationInitializer를 사용해서 등록합니다..
- 스프링 부트를 사용할 때는 자동으로 등록됩니다. (SecurityFilterAutoConfiguration)
FilterChainProxy
- 보통 “springSecurityFilterChain” 이라는 이름의 빈으로 등록된다.
#
16. AccessDecisionManager 1부Access Control 결정을 내리는 인터페이스로, 구현체 3가지를 기본으로 제공합니다.
- AffirmativeBased: 여러 Voter중에 한명이라도 허용하면 허용. 기본 전략.
- ConsensusBased: 다수결
- UnanimousBased: 만장일치
AccessDecisionVoter
- 해당 Authentication이 특정한 Object에 접근할 때 필요한 ConfigAttributes를 만족하는지 확인합니다.
- WebExpressionVoter: 웹 시큐리티에서 사용하는 기본 구현체, ROLE_Xxxx가 매치하는지 확인합니다.
- RoleHierarchyVoter: 계층형 ROLE 지원. ADMIN > MANAGER > USER
- ...
#
17. AccessDecisionManager 2부AccessDecisionManager 또는 Voter를 커스터마이징 하는 방법
계층형 ROLE 설정
#
18. FilterSecurityInterceptorAccessDecisionManager를 사용하여 Access Control 또는 예외 처리 하는 필터이며, 대부분의 경우 FilterChainProxy에 제일 마지막 필터로 들어있다.
#
19. ExceptionTranslationFilter필터 체인에서 발생하는 AccessDeniedException과 AuthenticationException을 처리하는 필터
AuthenticationException 발생 시
- AuthenticationEntryPoint 실행
- AbstractSecurityInterceptor 하위 클래스(예, FilterSecurityInterceptor)에서 발생하는 예외만 처리.
- 그렇다면 UsernamePasswordAuthenticationFilter에서 발생한 인증 에러는?
AccessDeniedException 발생 시
- 익명 사용자라면 AuthenticationEntryPoint 실행
- 익명 사용자가 아니면 AccessDeniedHandler에게 위임
#
20. 스프링 시큐리티 아키텍처 정리참고