1. SecurityContextHolder
- Spring Security의 인증 모델의 핵심
- SecurityContext가 들어있음 (현재 인증된 사용자 정보)
- 인증이 필요할 떄 꺼내서 사용 권한을 검사하거나 인증 여부를 확인함
- SecurityContextHolder에 인증 정보가 존재하면, 그 사용자는 인증된 사용자로 간주됨
저장 방식
ThreadLocal
- ThreadLocal을 이용해서 현재 인증 정보인 SecurityContext를 저장함
- 같은 스레드 내의 메서드들은 SecurityContext를 전달하지 않고도 사용할 수 있음
- 요청 처리가 끝나면 FilterChainProxy가 SecurityContext를 지워줌
저장 전략
전략 | 설명 | |
MODE_THREADLOCAL (기본값) |
현재 스레드에만 인증 정보 저장
|
|
MODE_INHERITABLETHREADLOCAL |
자식 스레드도 인증 정보 공유
|
비동기 처리 시, 인증 정보를 물려주기 위해 사용 |
MODE_GLOBAL |
JVM 전체에서 하나의 인증 정보를 공유
|
전체 인증정보를 모든 스레드에서 사용할 경우
|
- 시스템 속성(-Dspring.security.strategy=...) 설정
- 자바 코드에서 SecurityContextHolder.setStrategyName(...) 호출
예시
예) 인증 정보 꺼내기
더보기
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
String username = authentication.getName();
Object principal = authentication.getPrincipal();
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
- getName() → 사용자 이름 (username)
- getPrincipal() → 실제 사용자 정보 (보통 UserDetails)
- getAuthorities() → 권한(Role) 목록
예) 수동 설정
더보기
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication =
new TestingAuthenticationToken("username", "password", "ROLE_USER");
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
- SecurityContext 생성 및 Authentication 객체 담기
- SecurityContextHolder에 SecurityContext 저장
⚠️ SecurityContextHolder.getContext().setAuthentication(...)로 저장할 경우 race condition 위험이 있음
2. SecurityContext
- Authentication 객체를 담는 객체
3. Authentication
- 인증과 권한 부여를 위해 사용하는 가장 핵심적인 인터페이스
역할
구분 | 인증 요청 (인증 전) | 인증 완료 (인증 후) |
사용 목적 | 사용자 입력 자격 정보 전달 |
현재 로그인된 사용자 정보 표현
|
isAuthenticated() 값 | FALSE | TRUE |
principal | 사용자 ID (보통 String) |
사용자 정보 객체 (예: UserDetails)
|
credentials | 비밀번호 등 인증 정보 |
보통 null 처리됨 (보안상 삭제됨)
|
사용 예 | 로그인 시도 시 인증 요청 |
인증된 사용자 접근 권한 확인 시 사용
|
예시) 인증 요청
더보기
요청
AuthenticationManager.authenticate(...)
대표 구현체
new UsernamePasswordAuthenticationToken("id", "pw")
예시) 인증 완료
더보기
요청
SecurityContextHolder.getContext().getAuthentication()
대표 구현체
UsernamePasswordAuthenticationToken(UserDetails, null, authorities)
필드
필드명 | 설명 |
principal |
사용자 정보.
보통 UserDetails 구현체 (username, email, id 등) |
credentials |
비밀번호와 같은 민감 정보.
인증 후 보통 삭제됨 (null 처리) |
authorities |
권한 목록.
GrantedAuthority 리스트 (ROLE_USER, SCOPE_read 등) |
4. GrantedAuthority
- 사용자에게 부여된 권한을 나타내는 인터페이스
- prefix 사용 (ROLE_)
예) 꺼내기
더보기
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
5. AuthenticationManager
- 인증을 수행하는 핵심 인터페이스
- 인증 필터가 Authentication 객체를 만들고 이 객체를 AuthenticationManager에 전달함
- AuthenticationManager는 authenticate()를 호출하여 SecurityContextHolder에 인증 정보를 저장함
6. ProviderManager
- AuthenticationManager의 대표 구현체
- 여러 개의 AuthenticationProvider에게 인증을 위임하는 구조
인증 처리 흐름
- 클라이언트 요청이 들어오면 인증 필터가 Authentication 객체 생성
- ProviderManager.authenticate(authentication) 호출
- 내부적으로 등록된 AuthenticationProvider 목록을 순서대로 탐색
- AuthenticationProvider는 자신이 처리할 수 있는 Authentication만 처리함 (supports())
- 인증에 성공하면 인증된 Authentication 반환
- 인증 실패 시, 다음 provider로 위임
- 모든 provider가 인증을 처리하지 못하면, ProviderNotFoundException 예외 발생
Parent AuthenticationManager
- ProviderManager는 부모 AuthenticationManager를 가질 수 있음
- 모든 provider가 실패했을 때, 부모에게 인증 시도 위임
보안 처리
- credentials 자동 삭제
- 기본적으로 인증 성공 후 Authentication 객체에서 민감 정보는 삭제됨
7. AuthenticationProvider
- 특정 방식의 인증을 수행하는 컴포넌트
- supports() 메서드로 자신이 처리 가능한 인증 객체인지 확인 후, 인증을 수행함
대표 구현체
Provider | 인증 방식 |
DaoAuthenticationProvider |
아이디 + 비밀번호 (DB 조회)
|
JwtAuthenticationProvider | JWT 토큰 |
LdapAuthenticationProvider | LDAP 인증 |
커스텀 Provider |
예: Kakao OAuth, QR 인증 등 직접 구현 가능
|
8. Request Credentials with AuthenticationEntryPoint
AuthenticationEntryPoint
- 자격 증명 요청을 보낼 때 사용하는 인터페이스
- 모든 인증이 실패할 때, 어떻게 클라이언트에게 인증을 유도할 지 결정하는 엔트리 포인트
- 사용자의 인증 흐름을 시작시킴
상황 | 동작 방식 |
브라우저 기반 |
로그인 페이지로 리다이렉트 (/login)
|
REST API |
401 Unauthorized + WWW-Authenticate 헤더 응답
|
OAuth2 |
인증 서버로 리다이렉트
|
9. AbstractAuthenticationProcessingFilter
- 사용자의 인증 요청을 처리하는 기반 필터 클래스
- ex) UsernamePasswordAuthenticationFilter
인증 실패 시
- SecurityContextHolder.clearContext() → 보안 컨텍스트 초기화
- RememberMeServices.loginFail() 호출 (Remember-Me 기능이 설정되어 있다면 실패 처리)
- AuthenticationFailureHandler 실행 → 실패 후 처리 (예: 에러 페이지 리다이렉트)
인증 성공 시
- SessionAuthenticationStrategy 호출 → 세션 고정 보호, 세션 생성 등 처리
- 인증된 Authentication을 SecurityContextHolder에 저장
- 필요하면 SecurityContextRepository.saveContext(...)로 명시적 저장 (서블릿 필터 체인 이후에도 유지되게 하려면)
- RememberMeServices.loginSuccess() 호출 (remember-me 쿠키 설정 등)
- InteractiveAuthenticationSuccessEvent 이벤트 발행 (이벤트 리스너에서 후처리 가능)
- AuthenticationSuccessHandler 실행 → 로그인 성공 후 처리 (예: 대시보드 리다이렉트)
참고
'Spring > Spring Security' 카테고리의 다른 글
[Spring Security] 3-4. Authentication: logout (0) | 2023.10.03 |
---|---|
[Spring Security] 3-3. Authentication: Password Storage (0) | 2023.10.02 |
[Spring Security] 3-2. Authentication: Username/Password (2) | 2023.10.02 |
[Spring Security] 5. 예외 처리 (0) | 2023.09.30 |
[Spring Security] 1. Architecture (0) | 2021.07.28 |