시큐리티 인증 / 인가 흐름도
- AuthenticationManager
- 인증 필터로부터 Authentication 객체를 전달 받아 인증 시도
→ 인증 성공 시 사용자 정보, 권한 등을 포함한 Authentication 객체 반환 - AuthenticationManager는 여러 AuthenticationProvider들을 관리하며 AuthenticationProvider 목록을 순차적으로 순회하며 인증 요청을 처리
- AuthenticationProvider목록 중에서 인증 처리 요건에 맞는 적절한 AuthenticationProvider를 찾아 인증 처리 위임
- AuthenticationManagerBuilder에 의해 객체가 생성되며 주로 사용하는 구현체로 ProviderManager 제공
- 인증 필터로부터 Authentication 객체를 전달 받아 인증 시도
- AuthenticationManagerBuilder
- AuthenticationManager 객체를 생성 → UserDetailsService 및 AuthenticationProvider 추가 가능
- HttpSecurity.getSharedObject(AuthenticationManagerBuilder.class) 를 통해 객체를 참조 가능
AuthenticationManager 흐름도
- 선택적으로 부모 AuthenticationManage 구성 가능
→ 부모는 AuthenticationProvider 가 인증을 수행할 수 없는 경우에 추가적으로 탐색- OAuth2 인증 요청이 들어올 경우 ProviderManager가 가진 것으로는 처리가 불가
- 부모격의 ProviderMnager에게 요청
- 부모 ProviderManager는 OAuth2를 처리할 수 있는 Provider를 가짐 → 처리
- 일반적으로 AuthenticationProvider로 부터 null 이 아닌 응답을 받을 때 까지 차례대로 시도하며 응답을 받지 못하면 ProviderNotFoundException 발생과 함께 인증 실패
AuthenticationManager 사용 방법 1 - HttpSecurity 사용
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
AuthenticationManager authenticationManager = authenticationManagerBuilder.build(); // build() 는 최초 한번 만 호출해야 한다
AuthenticationManager authenticationManager = authenticationManagerBuilder.getObject(); // build() 후 getObject()로 참조
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/","/api/login").permitAll()
.anyRequest().authenticated())
.authenticationManager(authenticationManager) // 생성한 AuthenticationManager를 HttpSecurity에 저장
.addFilterBefore(customFilter(http, authenticationManager), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
// @Bean 선언 금지 -> AuthenticationManager는 bean이 아니기 때문에 주입 불가
public CustomAuthenticationFilter customFilter(HttpSecurity http, AuthenticationManager authenticationManager) {
CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(http);
customAuthenticationFilter.setAuthenticationManager(authenticationManager);
return customAuthenticationFilter;
}
AuthenticationManager 사용 방법 2 - 직접 생성
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeHttpRequests(auth -> auth
.requestMatchers("/","/api/login").permitAll()
.anyRequest().authenticated())
.addFilterBefore(customFilter(http), UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean // @Bean 선언 가능
public CustomAuthenticationFilter customFilter(HttpSecurity http) {
List<AuthenticationProvider> list1 = List.of(new DaoAuthenticationProvider());
ProviderManager parent = new ProviderManager(list1);
List<AuthenticationProvider> list2 = List.of(new AnonymousAuthenticationProvider("key"), new CustomAuthenticationProvider());
ProviderManager authenticationManager = new ProviderManager(list2, parent);
CustomAuthenticationFilter customAuthenticationFilter = new CustomAuthenticationFilter(http);
customAuthenticationFilter.setAuthenticationManager(authenticationManager);
return customAuthenticationFilter;
}
AuthenticationManager가 실질적으로 하는 역할은 별로 없음
- 인증필터(AuthenticationFilter)로부터 인증 토큰을 받아서 적절한 Provider를 찾아 선택하고 인증 토큰을 전달
- AuthenticationProvider에서 인증 절차를 수행하고 성공 시 유저 정보, 권한 등 모든 게 담긴 인증 토큰을 반환
- AuthenticationManager가 인증 필터에게 반환하는 중간자 역할
하지만 AuthenticationManager의 객체를 얻거나 직접 생성하는 방법을 알아야 CustomFilter를 만들어 적용할 수 있음
'Language > Spring Security' 카테고리의 다른 글
사용자 상세 서비스 - UserDetailsService (0) | 2024.07.24 |
---|---|
인증 제공자 - AuthenticationProvider (0) | 2024.07.24 |
인증 컨텍스트 - SecurityContext / SecurityContextHolder (0) | 2024.07.16 |
인증 - Authentication (0) | 2024.07.16 |
요청 캐시 - RequestCache / SavedRequest (0) | 2024.07.16 |