인증 아키텍처(3/13)

dev.hyjang·2024년 6월 1일

스프링 시큐리티

목록 보기
4/6

인증 – Authentication

인증(Authentication)

  • 특정 자원에 접근하려는 사용자의 신원을 확인
  • 신원에 따른 권한을 부여
  • 사용자의 인증 정보를 저장하는 토큰 개념의 객체로 활용
  • 인증 이후 SecurityContext에 저장되어 전역적을 참조가 가능

인증 절차 흐름


인증 컨텍스트 - SecurityContext / SecurityContextHolder

SecurityContextHolder, SercurityContext 구조

  • 스레드 마다 할당되는 전용 저장소에 SecurityContext를 저장하기 때문에 동시성 문제 없음!
  • 스레드 풀에서 운용되는 스레드일 경우, 새로운 요청이라도 기존의 TreadLocal 이 재사용될 수 있기 때문에 클라이언트로 응답 직전에 항상 SecurityContext를 삭제해 줌

SecurityContextHolderStrategy

  1. 기존 방식
SecurityContext context = SecurityContextHolder.createEmptyContext(); 
context.setAuthentication(authentication); 
SecurityContextHolder.setContext(context);
  • SecurityContextHolder를 통해 SecurityContext에 정적으로 접근할 때 여러 애플리케이션 컨텍스트가 SecurityContextHolderStrategy
    를 지정하려고 할 때 경쟁 조건을 만들 수 있음

  1. 변경된 방식
SecurityContextHolderStrategy securityContextHolderStrategy = SecurityContextHolder.getContextHolderStrategy();
SecurityContext context = securityContextHolderStrategy.createEmptyContext(); 
context.setAuthentication(authentication); 
securityContextHolderStrategy.setContext(context);
  • 애플리케이션이 SecurityContext를 정적으로 접근하는 대신 SecurityContextHolderStrategy 를 자동 주입이 될 수 있도록 함
  • 각 애플리케이션 컨텍스트는 자신에게 가장 적합한 보안 전략을 사용할 수 있음

인증 관리자 AuthenticationManager

AuthenticationManager

  • 인증 필터로부터 Authentication객체를 전달 받아 인증을 시도
  • 인증에 성공할 경우 사용자 정보, 권한 등을 포함한 완전히 채워진 Authentication 객체를 반환함
  • AuthenticationManager 는 여러 AuthenticationProvider 들을 관리
  • AuthenticationProvider 목록을 순차적으로 순회하며 인증 요청을 처리함
  • AuthenticationProvider 목록 중에서 인증 처리 요건에 맞는 적절한 AuthenticationProvider를 찾아 인증처리를 위임함
  • AuthenticationManagerBuilder에 의해 객체가 생성되며 주로 사용하는 구현체로 ProviderManager가 제공됨

AuthenticationManagerBuilder

  • AuthenticationManager 객체를 생성하며 UserDetailsService 및 AuthenticationProvider 를 추가
  • HttpSecurity.getSharedObject(AuthenticationManagerBuilder.class) 를 통해 객체를 참조

AuthenticationManager 흐름도

  • 선택적으로 부모 AuthenticationManager를 구성할 수 있으며 이 부모는 AuthenticationProvider 가 인증을 수행할 수 없는 경우에 추가적으로 탐색할 수 있음
  • 일반적으로 AuthenticationProvider로 부터 null 이 아닌 응답을 받을 때 까지 차례대로 시도
  • 응답을 받지 못하면 ProviderNotFoundException과 함께 인증이 실패!

1. HttpSecurity 사용

2. 직접 생성


인증 제공자 AuthenticationProvider

AuthenticationProvider

  • 사용자의 자격 증명을 확인하고 인증 과정을 관리하는 클래스
  • 사용자가 시스템에 액세스하기 위해 제공한 정보(아이디, 비밀번호)가 유효한지 검증하는 과정을 포함
  • 다양한 유형의 인증 메커니즘을 지원
    • 표준 사용자 이름과 비밀번호를 기반으로 한 인증
    • 토큰 기반 인증
    • 지문 인식 등
  • 인증 성공 후 Authentication 객체를 반환
  • 이 객체에는 사용자의 신원 정보와 인증된 자격 증명을 포함
  • 인증 과정 중에 문제가 발생한 경우 AuthenticationException 과 같은 예외를 발생시켜 문제를 알리는 역할을 함

AuthenticationProvider 흐름도

1. 일방 객체로 생성

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
 	AuthenticationManagerBuilder managerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
	managerBuilder.authenticationProvider(new CustomAuthenticationProvider());
 	http.authenticationProvider(new CustomAuthenticationProvider2());
 	http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
 	http.formLogin(Customizer.withDefaults());
	return http.build();
}

2. 빈으로 생성

  1. 빈 1개 정의
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http, AuthenticationManagerBuilder builder, AuthenticationConfiguration configuration) 
throws Exception {
 	AuthenticationManagerBuilder managerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
 	managerBuilder.authenticationProvider(customAuthenticationProvider());
 	ProviderManager providerManager = (ProviderManager)configuration.getAuthenticationManager();
 	providerManager.getProviders().remove(0);
 	builder.authenticationProvider(new DaoAuthenticationProvider());
 	http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
 	return http.build();
}
  • AuthenticationProvider를 빈으로 정의하면 DaoAuthenticationProvder를 자동으로 대체

  1. 빈 2개 이상 정의
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
	AuthenticationManagerBuilder managerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
 	managerBuilder.authenticationProvider(customAuthenticationProvider());
 	managerBuilder.authenticationProvider(customAuthenticationProvider2());
 	http.authorizeHttpRequests(auth -> auth.anyRequest().authenticated());
  	http.formLogin(Customizer.withDefaults());
 	return http.build();

@Bean
public AuthenticationProvider customAuthenticationProvider(){
 	return new CustomAuthenticationProvider();
}

@Bean
public AuthenticationProvider customAuthenticationProvider2(){
 	return new CustomAuthenticationProvider2();

사용자 상세 서비스 UserDetailsService

주요 기능

  • 사용자와 관련된 상세 데이터를 로드하는 것
  • 사용자의 신원, 권한, 자격 증명 등과 같은 정보를 포함
  • 이 인터페이를 사용하는 클래스는 주로 AuthenticationProvider
  • 사용자가 시스템에 존재하는지 여부와 사용자 데이터를 검색하고 인증 과정을 수행
AuthenticationManagerBuilder managerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
managerBuilder.userDetailsService(customUserDetailsService());
http.userDetailsService(customUserDetailsService());

사용자 상세 UserDetails

주요 기능

  • 사용자의 기본 정보를 저장하는 인터페이스
  • 스프링 시큐리티에서 사용하는 사용자 타입
isCredentialsNonExpired() //비밀번호 유효기간 확인
isAccountNonExpired() //계정 유효기간 확인
getUserName() //사용자 이름 반환
getAuthorities() //권한 반환
isAccountNonLocked() //잠김 여부 확인
getPassword() //비밀번호 반환
isEnabled() //활성화 여부 확인
profile
낭만감자

0개의 댓글