필자의 환경은
- Spring Boot 3.xxx
- Spring Security 6.xxx
시작전에 그래도 스프링 문서에있는 그림을 보자
그림은 좌에서 우로 설명된 기분이지만
실제 코드는 우에서 좌로 가야한다.. (알맹이부터...)
우선 라이브러리를 끼자
implementation 'org.springframework.boot:spring-boot-starter-security'
그리고 적당히 UserDetailsService나 PasswordEncoder 나 SecurityFilterChain Bean 등록하는 코드 적어둔다음
서버를 재시작하면서 디버깅하면된다.
스프링시큐리티의 내부로직은 너무 방대하기
이번 게시글에서는 제목대로 HttpSecurity, WebSecurity 이 두개에만 포커스를 맞춰보자
#1. HttpSecurityConfiguration 의 httpSecurity() 로 시작 (단, @Scope("prototype") )
@Scope("prototype") 이기 때문에 주입이 필요할때마다 동작한다
#1-2. AuthenticationConfiguration의 getAuthenticationManager() : AuthenticationManager (= ProviderManager)
AuthenticationManagerBuilder 객체를 생성하여 ProviderManager 를
parentAuthenticationManager 메서드를 통해 부모 인증관리자로 저장한다
#1-2-1 AuthenticationManagerBuilder의 performBuild() : ProviderManager
위의 #1-2 에서 AuthenticationManager 객체를 생성할때 실제 위임을 받아서
authBuilder.build() 로직을 타고 가다보면 결국 도착한다 (생략)
ProviderManager 를 빌드를 수행한다
즉, #1-2 전체과정으로 인증 관리자를 생성했다.
그리고 AuthenticationManagerBuilder 의 부모 인증 관리자로 지정했다.
#1-3 HttpSecurity 의 생성자 호출
HttpSecurity 의 생성자를 호출 함으로서 눈여겨 볼것은
this.setSharedObject 이다,
인증관리자의 구현직전의 빌더와 몇가지 객체를 공유객체로 따로 저장하는 것을 볼 수있다
따라서 HttpSecurity 를 주입받으면 저 공유객체속 인증관리자 빌더를 꺼내서 우리가 원하는
Provider 들을 지정할 수 있다
그리고 AuthenticationManagerBuilder를 아까
parentAuthenticationManager 메서드를 통해 부모 인증관리자로 저장했던걸 확인할 수 있다
그리고 AuthenticationManagerBuilder 속 parentAuthenticationManager 필드의 providers 을 보면
DaoAuthenticationProvider 가 있다, 이런 인증관리자 내부에 List로 가지고 있는 요소를
프로바이더(Provider) 라고 부른다
실제 인증로직의 핵심을 담당한다. 매니저는 위임을 할뿐이다. (참고)
다음으로 HttpSecurity 자체가 갖고있는 AuthenticationManager 를 보면
아직 null 인것을 알 수 있고, 공유 객체는 잘들어와 있다
*참고
sharedObjects 는 Map이다
*참고
DaoAuthenticationProvider 은 UserDetailsService를 통해 사용자를 조회하는 역할을 한다
여기까지만 해도 정말 내가 코드친게 없는데 이루어지는 로직이다
이제부터가 시작이다 !
#2. 개발자가 생성한 @Bean SecurityFilterChain 이 HttpSecurity 를 주입 받는다
이때 #1의 전체 과정의 HttpSecurity 를 주입 받는다
그렇다면 위의 과정을 통해 얻은 것은 다음과 같다
[첫번째]
부모 인증관리자도 생성되었을것이며 타입은 정확하게 ProviderManager 일것이다
[두번쨰]
공유객체는 세개가 저장되어 있었고
우리의 주인공은 AuthenticationManagerBuilder 였다 AuthenticationManager가 되기 직전의 형태라고 보자
#2. 개발자가 생성한 @Bean SecurityFilterChain 내부
주입받은 HttpSecurity를 build() 하면
최종적으로 HttpSecurity 의 performBuild() 가 호출된다
리턴 타입은 DefaultSecurityFilterChain 이다
이렇게 필터들을 갖은 하나의 SecurityFilterChain이 생성된다
#3. WebSecurityConfiguration 의 setFilterChains 메서드 호출
#2 에서 만들 SecurityFilterChain을 리스트로 갖는 컬렉션을 주입받는다
참고로 SecurityFilterChain은 여러개 생성할 수 있으니 컬렉션으로 받는다
#3. WebSecurityConfiguration 의 springSecurityFilterChain 메서드 호출
정확히 FilterChainProxy 을 생성하기 위함이다 ( FilterChainProxy 은 GenericFilterBean 을 상속한다 )
#3. WebSecurity의 performBuild() 메서드 호출 (최종적으로)
앞서 build 하면 결국 WebSecurity 의 performBuild() 메서드가 호출되는데
모든 보안설정들을 가지고있는 FilterChainProxy 를 생성한다
그러면 스프링 시큐리티 문서와 닮은 그림이 나온다
혼자 공부할겸 한번 글을 작성해봤는데
도움이 될지 모르겠다.
'개발 > spring-security' 카테고리의 다른 글
rememberMe 에 대하여 (4) | 2024.10.26 |
---|---|
jwt 토큰 생성하고 검증해보자 (0) | 2024.06.01 |
spring security 와 jwt 주저리 (0) | 2024.06.01 |
JWT 토큰 (0) | 2024.06.01 |
커스텀 Filter 에 AuthenticationManager 공유하기 (0) | 2024.05.23 |