스프링 빈
은 스프링 컨테이너(예: ApplicationContext)에서 관리되는 객체로 스프링 빈은 스프링 컨테이너가 생성하고 관리하므로 서블릿 필터가 직접 빈에 접근하거나 주입받는 것이 불가능.
스프링 시큐리티는 서블릿 필터를 사용하여 웹 요청을 보호합니다. DelegatingFilterProxy
는 이러한 스프링 시큐리티 필터를 서블릿 필터와 통합하는 역할을 합니다.
서블릿 필터는 스프링 빈에 직접 접근하지 않지만, DelegatingFilterProxy를 통해 스프링 컨테이너에서 관리되는 빈을 사용할 수 있습니다.
그래서 서블릿 필터가 관리하는 DelegatingFilterProxy
가 SpringSecurityFilterChain
(=FilterChainProxy) 이름으로 생성된 빈에 요청을 위임 그 후, DelegatingFilterProxy이름으로 필터 등록
FilterChainProxy : SpringSecurityFilterChain 의 이름으로 생성된 빈으로 DelegatingFilterProxy의 요청을 위임받아 실제 보안처리를 함.
스프링 시큐리티 초기화 시 생성되는 기본필터들과 사용자가 생성한 필터들을 관리하고 제어
SecurityContext
에 저장되어 전역적으로 참조가 가능하다Authentication authentication = SecurityContexHolder
.getContext()
.getAuthentication()
1. UsernamePasswordAuth필터가 입력받은 아이디와 비밀번호를 추출해서 Authentication 객체를 만들고 AuthenticationManager에 전달
2. AuthenticationManager에서 인증처리를 하고 성공하면 Authentication 객체를 만들어서 SecurityContextHolder에 전달
1. Authentication 객체가 저장되는 보관소로 필요 시 언제든지 Authentication 객체를 꺼내어 쓸 수 있도록 제공되는 클래스
2. ThreadLocal 에 저장되어 아무 곳에서나 참조가 가능하도록 설계함
3. 인증이 완료되면 HttpSession에 저장되어 어플리케이션 전반에 걸쳐 전역적인 참조가 가능하다
SecurityContext 객체 저장 방식
SecurityContextHolder.clearContext() : SecurityContext 기존 정보 초기화
로그인을 하면 사용자의 요청을 받은 쓰레드와 쓰레드 전역 저장소가 생성됨
사용자 요청을 받을 때마다 SecurityContext 객체의 생성, 저장, 조회
익명 사용자
새로운 SecurityContext 객체를 생성하여 SecurityContextHolder 에 저장
AnonymousAuthenticationFilter 에서 AnonymousAuthenticationToken 객체를 SecurityContext 에 저장
아이디와 비밀번호로 인증 시
새로운 SecurityContext 객체를 생성하여 SecurityContextHolder 에 저장
UsernamePasswordAuthenticationFilter 에서 인증 성공 후 SecurityContext 에 UsernamePasswordAuthentication token객체를 SecurityContext 에 저장
인증이 최종 완료되면 Session 에 SecurityContext 를 저장
인증 후
Session 에서 SecurityContext 꺼내어 SecurityContextHolder 에서 저장
SecurityContext 안에 Authentication 객체가 존재하면 계속 인증을 유지한다
최종 응답 시 공통 : 요청에 응답 시 Holder에서 Context를 제거하고 response
SecurityContextHolder.clearContext()
AuthenticationManager
를 통해 이루어지며, AuthenticationManagerBuilder
가 AuthenticationManager를 생성한다. 전체적인 설정은 AuthenticationManager에 하고 실제 인증처리는 AuthenticationProvider에서 진행한다. @Bean
protected void AuthenticationManager(AuthenticationManagerBuilder auth)
{
auth.userDetailsService(memberService)
// userDetailsService 를 구현하고 있는 객체를 지정
.passwordEncoder(passwordEncoder());
} ==> 스프링 부트 버전 업데이트 이후 없어도 되는 코드
UserDetailService
인터페이스는 DB에서 회원정보를 가져오는 역할을 한다. 인터페이스를 구현하여 그 안에 loadUserByUsername()
메서드로 회원정보를 조회하고, UserDetailService가 repository에서 찾아온 유저의 정보는 User 객체
로 만들어져 반환된다. 그리고 입력받은 아이디와 비밀번호가 담긴 Authetication와 실제 아이디, 비밀번호를 비교해서 검증한다.인증 받은 사용자에게 무엇이 허가 되었는지 증명하는 것
FilterSecurityInterceptor
인증 정보
, 요청정보
, 권한정보
를 이용해서 사용자의 자원접근을 허용할 것인지 거부할 것인지를 최종 결정하는 주체AffirmativeBased
: 기본값으로 여러개의 Voter 클래스 중 하나라도 접근 허가로 결론을 내면 접근 허가로 판단한다.
ConsensusBase
: 다수표(승인 및 거부)에 의해 최종 결정을 판단한다
동수일경우 기본은 접근허가이나 allowIfEqualGrantedDeniedDecisions 을 false 로 설정할 경우 접근거부로 결정된다
UnanimousBased
: 모든 보터가 만장일치로 접근을 승인해야 하며 그렇지 않은 경우 접근을 거부한다