[Security] 인증(Authentication) 개념편
관련 나의 블로그 | |
[Security] 접근 제어 정책(Access Control) | https://jm-baek.tistory.com/370 |
[Security] Spring Security 개념편 | https://jm-baek.tistory.com/386 |
✅ [Security] 인증(Authentication) 개념편 | https://jm-baek.tistory.com/385 |
[Security] 인가(Authorization) 개념편 | https://jm-baek.tistory.com/389 |
[Security]Spring Security 도입 구상편 | https://jm-baek.tistory.com/388 |
[Security] Spring Security 도입편 |
혼자 고민하고 정리해서 서툴고 틀린 방향이 있을 수 있습니다.
좋은 충고와 질문은 어제든 감사드립니다.
🙇♂️ 빠른 시일 내에 작성을 하도록 하겠습니다.....🙇♂️
목차
- 들어가기에 앞서
- Servlet Authentication Architecture
🎯 들어가기에 앞서
spring security filter가 어떻게 구성되었는지 개념편에서 파악을 했으면, 세부적으로 인증(Authentication)을 어떻게 처리하고 있는지 자세하게 알아보자!!
Servlet Authentication Architecture
1️⃣ SecurityContextHolder
Spring Security에서 SecurityContextHolder는 ⭐ 현재 인증된 사용자 정보를 저장하는 공간이다.
Spring Security 자체는 SecurityContextHolder가 어떻게 채워지는지에 대해 신경 쓰지 않으며, 단순히 값이 존재하는 경우 이를 현재 인증된 사용자로 간주한다.
가장 간단한 방법으로 인증된 사용자를 나타내려면 SecurityContextHolder를 직접 설정하면 된다.
SecurityContextHolder 설정 예시
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication =
new TestingAuthenticationToken("username", "password", "ROLE_USER");
context.setAuthentication(authentication);
SecurityContextHolder.setContext(context);
2️⃣ SecurityContext
- SecurityContext는 SecurityContextHolder에서 가져올 수 있다.
- 내부에는 Authentication 객체를 포함하고 있으며, ⭐ 현재 인증된 사용자 정보를 저장한다.
3️⃣ Authentication
Authentication 인터페이스는 Spring Security에서 두 가지 주요 역할을 수행한다.
- ⭐ 인증 요청 시 입력값으로 사용
- 사용자가 제공한 자격 증명(credentials) 을 AuthenticationManager에 전달하여 인증을 수행한다.
- 이때 isAuthenticated() 메서드는 false를 반환한다.
- ⭐ 현재 인증된 사용자 정보 저장
- SecurityContext에서 현재 인증된 사용자의 Authentication 객체를 가져올 수 있다.
- 인증이 완료되면 isAuthenticated()는 true가 된다.
Authentication 객체의 구성 요소
속성 | 설명 |
principal | 사용자 식별 정보. 일반적으로 UserDetails 객체가 들어감. |
credentials | 비밀번호 등의 인증 정보. 보안을 위해 인증 후 제거될 수 있음. |
authorities | GrantedAuthority 목록으로, 사용자가 가진 권한(역할/범위) 포함. |
예제 코드
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();
Object principal = authentication.getPrincipal(); // 사용자 정보
Object credentials = authentication.getCredentials(); // 비밀번호 (보통 인증 후 null 처리됨)
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities(); // 권한 목록
4️⃣ GrantedAuthority
GrantedAuthority 객체는 사용자가 부여받은 고수준(high-level)의 권한을 나타낸다.
일반적으로 두 가지 유형의 권한이 있다.
- Roles (역할) → ROLE_ADMINISTRATOR, ROLE_HR_SUPERVISOR 등
- Scopes (범위) → OAuth2에서 사용되는 특정 액세스 범위
GrantedAuthority 가져오기
Authentication.getAuthorities() 메서드를 사용하면 현재 사용자에게 부여된 GrantedAuthority 목록을 가져올 수 있다.
- GrantedAuthority 객체는 사용자가 가진 권한을 나타내며,
Spring Security에서는 웹 보안, 메서드 보안, 도메인 객체 보안 등 다양한 영역에서 사용된다. - 역할 기반 접근 제어(Role-Based Access Control, RBAC)를 구현할 때 필수적인 개념이다.
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
GrantedAuthority는 특정 도메인 객체 권한을 표현하지 않음
- 보통 GrantedAuthority 객체는 애플리케이션 전반에 걸친 전역 권한을 의미한다.
- 특정 도메인 객체(예: 직원 ID 54번에 대한 접근 권한)를 GrantedAuthority로 표현하는 것은 적절하지 않다.
이유
- 수천 개의 개별 객체에 대한 권한을 GrantedAuthority로 생성하면 메모리 과부하 및 인증 속도 저하 문제 발생 가능
- Spring Security는 이런 문제를 해결하기 위해 도메인 객체 보안 기능을 제공
도메인 객체 관리 권한 예시
@PreAuthorize("hasPermission(#employee, 'READ')")
public Employee getEmployee(Long id) {
return employeeRepository.findById(id).orElseThrow();
}
5️⃣ AuthenticationManager
AuthenticationManager는 ⭐️ Spring Security의 필터들이 인증을 수행하는 방법을 정의하는 API입니다. 반환된 Authentication 객체는 이를 호출한 컨트롤러(즉, Spring Security의 필터 인스턴스)에 의해 SecurityContextHolder에 설정됩니다.
Spring Security의 필터 인스턴스와 통합하지 않는 경우, SecurityContextHolder를 직접 설정할 수 있으며 반드시 AuthenticationManager를 사용할 필요는 없습니다.
AuthenticationManager의 구현 방식은 다양할 수 있지만, 가장 일반적인 구현체는 ProviderManager입니다.
6️⃣ ProviderManager
ProviderManager는 가장 일반적으로 사용되는 ⭐️ AuthenticationManager 구현체입니다.
ProviderManager는 여러 AuthenticationProvider 인스턴스를 가진 리스트에 위임합니다. 각 AuthenticationProvider는 인증이 성공해야 한다고 알리거나, 인증 실패를 알리거나, 결정을 내릴 수 없음을 알리고 이후의 AuthenticationProvider가 결정을 내릴 수 있도록 합니다.
만약 설정된 AuthenticationProvider 인스턴스 중 어느 것도 인증을 할 수 없다면, 인증은 ProviderNotFoundException으로 실패하게 되며, 이는 제공된 인증 유형을 지원하도록 ProviderManager가 구성되지 않았음을 나타내는 특별한 AuthenticationException입니다.
실제로 각 AuthenticationProvider는 특정 유형의 인증을 수행하는 방법을 알고 있습니다. 예를 들어, 하나의 AuthenticationProvider는 사용자 이름/비밀번호를 검증할 수 있고, 다른 하나는 SAML 어설션을 인증할 수 있습니다. 이렇게 함으로써 각 AuthenticationProvider는 매우 구체적인 유형의 인증을 수행하면서도 여러 유형의 인증을 지원하고, 단일 AuthenticationManager 빈만 노출할 수 있습니다.
ProviderManager는 또한 선택적인 부모 AuthenticationManager를 구성할 수 있으며, 이는 인증을 수행할 수 있는 AuthenticationProvider가 없을 경우 참조됩니다. 부모는 어떤 유형의 AuthenticationManager도 될 수 있지만, 일반적으로는 ProviderManager의 인스턴스인 경우가 많습니다.
실제로 여러 개의 ProviderManager 인스턴스가 동일한 부모 AuthenticationManager를 공유할 수 있습니다. 이는 여러 개의 SecurityFilterChain 인스턴스가 일부 공통된 인증(공유된 부모 AuthenticationManager)을 가지고 있지만, 서로 다른 인증 메커니즘(각각의 ProviderManager 인스턴스)을 사용하는 경우에 종종 발생합니다.
기본적으로, ProviderManager는 성공적인 인증 요청에 의해 반환된 Authentication 객체에서 민감한 자격 증명 정보를 삭제하려고 시도합니다. 이는 비밀번호와 같은 정보가 HttpSession에 필요 이상으로 오래 보관되는 것을 방지합니다.
7️⃣ AbstractAuthenticationProcessingFilter
참고 사이트
- 스프링 시큐리티 - 인가(https://docs.spring.io/spring-security/reference/servlet/authorization/index.html)
- 스프링 시큐리티 - 인증/승인(https://docs.spring.io/spring-security/reference/servlet/authentication/index.html)
- 인가 및 인증