스프링 시큐리티는 서블릿 필터를 이용해 인증 인가 처리를 함 그런데 스프링 시큐리티에서 정의한 필터빈들은 스프링 컨테이너 빈임 그러면 어떻게 하냐 DelegatingFilterProxy
가 특정 스프링 컨테이너에 있는 FilterChainProxy
으로 등록된 빈을 찾아 필터를 위임 함
참고로 DelegatingFilterProxy는 스프링 시큐리티 기술이 아니라 스프링 웹 표준 기술임 스프링의 빈으로 등록하면 스프링 컨텍스트에 등록된 빈을 사용 할 수 있는게 가장 큰 장점임
DelegatingFilterProxy
까지 필터가 전달 되면 DelegatingFilterProxy
는 스프링 컨텍스트에 등록된 Bean
이름이 springSecurityFilterChain
으로 된 FilterChainProxy
를 찾는다.FilterChainProxy
는 SpringSecurityConfig
에 등록된 필터들을 순서에 맞게 필터 체이닝 함DispatcherServlet
으로 요청으로 감Autentication
는 스프링 시큐리티에서 인증 시 사용자의 인증 정보를 저장하는 토큰 개념의 객체이다SecurityContext
에 저장되어 스프링 전역적 으로 참조가 가능하다.Authtentication authentication = SeurityContextHolder.getContext().getAuthentication()
Authentication
이 담고있는 프로퍼티principal
: 사용자 아이디 혹은 User
객체를 저장credentials
: 사용자 비밀번호authorites
: 인증된 사용자의 권한 목록 Rolesdetails
: 인증 부가 정보Authenticated
: 인증 여부UsernamePasswordAuthentication
은 Authentication
객체를 만듬Authentication
는 AuthtenticationManger
를 통해 인증을 함 (실패하면 예외 발생)Authentication
는 SecurityContext
에 전역적으로 사용할 수 있음Authentication
객체가 저장되는 보관소로 필요시 언제든지 Authentication
객체를 꺼내어 쓸 수 있도록 제공된다
TheardLocal
에 저장되어 현재 실행되고 있는 스레드에 스택프레임에 있는 곳 아무데서나 사용이 가능하다.
인증이 완료되면 HttpSession
에 저장되어 어플리케이션 전반에 걸쳐 전역적인 참조 가능하다
SecurityContext
를 담고 있고 SecurityContext
를 현재 쓰레드와 연결 해준다
SecurityContext
객체 저장 방식
MODE_THREADLOCAL
: 스레드당 SecurityContext
객체를 할당 (default) 한다
MODE_INHERITABLETHREADLOCAL
: 메인 스레드에서 자식 스레드를 생성할 경우 자식 스레드는 메인 스레드의 동일 한SeucirytContext
를 유지 한다
MODE_GLOBAL
: 응용 프로그램에서 단 하나의 SecurityContext
만 존재한다.
SecurityContext
를 저장 한다.SecurityContext
의 생성, 조회, 저장 등 라이프 사이클을 관리 하는 필터
매 요청시마다 항상 동작하고 스프링 시큐리티의 2번 째 필터로 등록 되어있다
HttpSecurityContextRepository
를 이용해 영속화를 책임짐 기본적으로 구현체는 HttpSessionSecurityContextRepository
를 사용함요청이 들어오면
HttpSecurityContextRepository
load
메서드를 이용해 SecurityContext
를 로드 함
HttpSessionSecurityContextRepository
를 이용 한다고 했음 session
을 조회해서 만약 session
이 존재하지 않으면 SecurityContext
는 authenticated - false
인 객체를 반환 할거임 load
되었으면 다음 chain
으로 넘긴다 인증되지 않은 SecurityContext
는 인증 처리를 하는 필터를 처리하겠지만 인증된 SecurityContext
는 인증 필터를 처리하지 않을 것임
UsernamePasswordAuthenticationFilter
로 id + password 인증 요청이 들어옴
UsernamePasswordAuthenticationFilter
는 id + password 를 담은 Authentication
토큰을 생성 함
AuthenticationManger
로 Authentication
토큰을 남겨 인증 처리를 위임함
AuthenticationManger
는 실제 인증 역할을 하지 않고 id + password 인증을 하는 적절한 AutenticationProvder
를 찾아 인증 역할을 위임 함
AutenticationProvder
는 실제 인증 처리 역할을 함 유저 유효성 검증 처리 등
loadUserByUsername
의 역할은 username
을 이용해 실제 영속화된 객체를 조회함
loadUserByUsername
는 Authentication
의 UserDetails
를 반환 함
만약 조회하는데 실패하면 UsernameNotFoundException
을 발생 시켜야 함
AutenticationProvder
는 반환받은 UserDetails
와 실제 password
를 검증 한다
일치하지 않는 경우 BadCredentialException
예외 발생
검증에 성공 할 경우 UserDetails
+ UserDetails.authorites
를 이용 해 Authenticaiton
토큰 객체 생성
그 후 생성된 SecurityContext
토큰을 저장
AuthenticationProvider 목록 중에서 인증 처리 요건에 맞는 AuthenticationProvider 찾아 인증을 위임하는 역할
구현체로는 ProviderManager가 있음
부모 ProviderManager 를 설정하여 AuthenticationProvider를 계속 탐색 할 수 있다.
필터체인 맨 마지막에 위치한 필터로써 인증된 사용자에 대하여 특정 요청의 승인/거부 여부를 최종적으로 결정
인증객체 없이 보호자원에 접근을 시도할 경우 AuthenticationExcetpion
을 발생
인증 후 자원에 접근 가능한이 존재하지 않을 경우 AccessDeniedException
을 발생
권한 제어 방식 중 HTTP 자원의 보안을 처리하는 필터
권한 처리를 AccessDecisionManager에게 맡김
FilterSecurityInterceptor
에서 요청을 받으면 Authentication
의 인증객체 여부를 체크 함
Authentication
이 null
이면 AuthenticationException
예외를 던져 ExceptionTranslationFilter
가 예외 처리를 함Authentication
객체가 null
이 아니면 SecurityMetadataSource
에서 권한 정보들을 가져 옴
SecurityMetadataSource
가 null
일 경우 권한 심사를 하지 않고 바로 자원 접근 허용 함권한 정보가 있을 경우 FilterSecurityInterceptor
는 AccessDecisionManager
에게 권한 심사를 위임 함
AccessDeniedException
예외를 터트려 ExceptionTranslationFilter
가 예외 처리를 함