1. SecurityContextHolder

- 현재 실행 흐름에서 사용중인 SecurityContext를 보관하고 조회하기 위한 정적 접근 지점
- ✅ 인증이 필요할 때 꺼내서 사용 권한을 검사하거나 인증 여부를 확인함
예) 인증 정보 꺼내기
더보기
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 저장
더보기
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 위험이 있음
SecurityContextHolderStrategy
| 전략 | 설명 | 특징 |
| MODE_THREADLOCAL (기본값) |
현재 스레드에만 인증 정보 저장
|
요청 처리가 끝나면 SecurityContextPersistenceFilter가 SecurityContext를 지움
|
| MODE_INHERITABLETHREADLOCAL |
자식 스레드도 인증 정보 공유
|
직접 생성한 자식 스레드에는 사용할 수 있지만 스레드 풀 기반 비동기 처리엔 주의 필요 |
| MODE_GLOBAL |
JVM 전체에서 하나의 인증 정보를 공유
|
일반적인 다중 사용자 웹 애플리케이션에선 부적합
|
셋팅 방법
더보기
- JVM 시스템 속성: -Dspring.security.strategy=...
- Java 코드: SecurityContextHolder.setStrategyName
2. SecurityContext
- Authentication 객체를 담는 컨테이너
3. Authentication
- 인증 요청과 인증 결과를 표현하는 핵심 인터페이스
- ✅ 인가 과정에서는 현재 사용자와 권한 정보를 제공함
필드
| 필드명 | 설명 | 예시 / 특징 |
| principal | 사용자 정보 |
- Username/Password: UserDetails 구현체
- JWT: Jwt - OAuth2 Login: OAuth2User or OidcUser - Anonymous: 익명 사용자 정보 |
| credentials | 민감 정보 (비밀번호 등) |
인증 후 삭제됨 (null 처리)
|
| authorities | 권한 목록 |
GrantedAuthority 리스트 (ROLE_USER, SCOPE_read 등)
|
역할
| 구분 | 인증 요청 (인증 전) | 인증 완료 (인증 후) |
| 사용 목적 | 사용자 입력 자격 정보 전달 |
현재 로그인된 사용자 정보 표현
|
| principal | 사용자 ID (보통 String) |
사용자 정보 객체 (예: UserDetails)
|
| credentials | 비밀번호 등 인증 정보 |
보통 null 처리됨 (보안상 삭제됨)
|
| 예시 | 로그인 시도 시 인증 요청 |
인증된 사용자 접근 권한 확인 시 사용
|
예시) 인증 요청
더보기
요청
AuthenticationManager.authenticate(...)
대표 구현체
new UsernamePasswordAuthenticationToken("id", "pw")
예시) 인증 완료
더보기
요청
SecurityContextHolder.getContext().getAuthentication()
대표 구현체
UsernamePasswordAuthenticationToken(UserDetails, null, authorities)
4. GrantedAuthority
- 사용자에게 부여된 권한을 나타내는 인터페이스
- ✅ 인가는 Authentication의 권한 목록을 조회하고 getAuthority()가 반환하는 문자열을 비교하여 이루어짐
예) 꺼내기
더보기
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
Collection<? extends GrantedAuthority> authorities = auth.getAuthorities();
prefix 규칙
- ROLE_: 역할을 나타내는 관례로 쓰임. hasRole() API를 제공함 (prefix를 자동으로 붙여 권한을 검사함)
- SCOPE_: JWT 또는 OAuth2 Resource Server에서 토큰의 scope 권한을 GrantedAuthority로 변환할 때 쓰임
5. AuthenticationManager
- 인증을 수행하는 핵심 인터페이스
- ✅ 인증의 진입점 역할을 담당함 (인증 필터가 Authentication 객체를 만들고 이 객체를 AuthenticationManager에 전달함)
- ✅ 인증에 성공하면 완성된 Authentication을 반환함
6. ProviderManager


- AuthenticationManager의 대표 구현체
- ✅ 여러 개의 AuthenticationProvider에게 인증을 위임하는 구조
인증 처리 흐름
- 클라이언트 요청이 들어오면 인증 필터가 Authentication 객체를 생성함
- ProviderManager.authenticate(authentication) 호출
- null 반환 시, 다음 provider로 위임
- 일반 AuthenticationException 예외 시, 해당 예외를 기억하고 계속 진행함 (다음 provider에 위임)
- ex) BadCredentialsException, UsernameNotFoundException 등
- 내부적으로 등록된 AuthenticationProvider 목록을 순서대로 탐색
- 인증에 성공하면 인증된 Authentication 반환
- 지원하지 않을 경우, 다음 provider로 위임됨 (supports()가 false)
- 판단 포기 시, null이 반환되며 다음 provider로 위임됨 (이번 요청에 대해서는 최종 인증 결정을 내리지 않겠다는 뜻)
- 전달된 Authentication 타입을 지원하는 provider를 찾지 못하면, ProviderNotFoundException 예외 발생
Parent AuthenticationManager

- ProviderManager는 부모 AuthenticationManager를 가질 수 있음
- 현재 ProviderManager의 Provider 목록에서 최종 인증 결과를 얻지 못했을 때, 부모에게 인증 시도를 위임할 수 있음
보안 처리
- 인증 성공 후 Authentication 객체에서 민감 정보(credentials)는 보통 null 처리됨
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 응답
|
| HTTP Basic / Bearer Token |
401 Unauthorized + WWW-Authenticate 헤더 응답
|
| OAuth2 |
OAuth2 인증 시작 URL로 리다이렉트
|
9. AbstractAuthenticationProcessingFilter

- 사용자의 인증 요청을 처리하는 기반 필터 클래스
- ex) UsernamePasswordAuthenticationFilter
인증 성공 시
- SessionAuthenticationStrategy 호출 → 세션 고정 보호, 세션 생성 등
- 인증된 Authentication을 SecurityContextHolder에 저장
- 필요하면 SecurityContextRepository.saveContext(...)로 저장 (서블릿 필터 체인 이후에도 유지되도록 함)
- RememberMeServices.loginSuccess() 호출 → remember-me 쿠키 설정 등
- InteractiveAuthenticationSuccessEvent 이벤트 발행 → 이벤트 리스너에서 후처리 가능
- AuthenticationSuccessHandler 실행 → 로그인 성공 후 처리 (예: 대시보드 리다이렉트)
인증 실패 시
- 계정 상태: LockedException, DisabledException, AccountExpiredException, CredentialsExpiredException 등
- 내부 시스템 오류: InternalAuthenticationServiceException 등 (db 장애, 외부 인증 시스템 오류 등)
- SecurityContextHolder.clearContext() → 보안 컨텍스트 초기화
- RememberMeServices.loginFail() 호출 → Remember-Me 기능이 설정되어 있다면 실패 처리
- AuthenticationFailureHandler 실행 → 실패 후 처리 (예: 에러 페이지 리다이렉트)
참고
'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 |