Spring Security
Spring Security는 강력하고 사용자 정의가 가능한 인증 및 액세스 제어 프레임워크입니다.
Spring 기반 애플리케이션 보안을 위한 사실상 표준 프레임워크며 사용자 인증, 권한 부여, 세션 관리, CSRF(Cross-Site Request Forgery) 및 XSS(Cross-Site Scripting) 방어, 보안 헤더 설정, 사용자 로그인 및 로그아웃 관리, 접근 제어, 그리고 다양한 인증 및 인가 메커니즘을 제공하여 웹 애플리케이션의 보안을 강화할 수 있습니다.
또한 Spring Web MVC와 선택적 통합을 제공하여 웹 애플리케이션의 보안 구현을 간편하게 설정 할 수 있습니다.
Spring Security의 필터 체인(Filter Chain)을 사용하요 HTTP 요청을 순차적으로 처리할 수 있으며 @PreAuthorize, @PostAuthorize, @Secured, @RolesAllowed
와 같은 어노테이션을 사용하여 메소드 레벨에서 권한 부여를 지정할 수 있습니다.
또한 SecurityContextHolder
를 사용하여 현재 클라이언트의 Principal, Credential
객체를 얻어 클라이언트의 권한을 확인하는 등의 작업을 할 수 있습니다.
Architecture
위의 이미지는 최초 사용자가 요청한 HttpRequest를 Spring Security에서 어떤 과정을 걸쳐서 사용자의 인증 & 인가 처리를 하는지 나타내는 도식입니다.
성공적으로 완료된 사용자는 SecurityContext에 인증 & 인가 정보가 저장되여 애플리케이션 전역에서 사용할 수 있습니다.
다음은 Spring Security의 주요 핵심 컴포넌트들에 대한 설명입니다.
Authentication Filter
Authentication Filter는 사용자의 인증(Authentication) 및 인가(Authorization) 프로세스를 처리하는 Spring Security 필터 체인의 일부로 사용자 정의 필터를 추가하거나 구성하여 특정 요구 사항에 맞게 동작을 확장하고 수정할 수 있습니다.
클라이언트 요청이 서버에 도달할 때 실행되며 주요 역할은 사용자의 인증 정보를 검증하고 검증이 완료된 사용자의 인증 정보를 SecurityContextHolder에 저장하는 역활을 합니다.
다음은 Spring Security에서 기본적으로 제공하는 Authentication Filter 입니다.
- UsernamePasswordAuthenticationFilter: 클라이언트가 요청한 사용자 이름과 비밀번호를 인증하기 위한 필터입니다.
UsernamePasswordAuthenticationToken
토큰을 생성하여 Authentication Manager에 인증을 요청합니다. - BasicAuthenticationFilter: 클라이언트가 요청 헤더에 인증 정보를 포함시키면 해당 정보를 추출하고 사용자를 인증합니다.
- BearerTokenAuthenticationFilter: JWT(JSON Web Token) 또는 OAuth 2.0의 Bearer 토큰을 사용한 인증을 처리합니다. 클라이언트가 요청 헤더 또는 쿼리 매개변수에 토큰을확인하여 검증하고 사용자를 인증합니다.
- SessionManagementFilter: 세션 관리를 위해 세션 고정 방지 및 세션 만료 처리를 담당합니다.
- RememberMeAuthenticationFilter: 용자가 로그아웃한 후에도 다시 로그인할 때 사용자를 인증합니다.
- AnonymousAuthenticationFilter: 인증되지 않은 사용자를 위하여 임의의 익명 사용자를 생성하고 익명 사용자 전용 권한을 부여합니다.
Authentication Manager
Authentication Manager는 전달된 인증 객체를 인증을 시도(Attempts)하며 인증에 성공하면 완전히 채워진 인증 객체와 부여된 권한을 포함해 반환합니다.
즉 사용자의 인증(Authentication)을 관리하고 검증하는 인터페이스입니다.
그 중 org.springframework.security.authentication.ProviderManager
는 Spring Security에서 기본적으로 제공하는 구현체로 여러 개의 org.springframework.security.authentication.AuthenticationProvider
를 가지고 있으며 AuthenticationProvider
를 통해 사용자 인증을 진행합니다.ProviderManager
는 클라이언트의 인증 요청이 들어오면 등록된 AuthenticationProvider
목록을 반복하여 각각의 AuthenticationProvider
가 처리할 수 있는 인증 로직을 수행하여 인증에 성공하면 org.springframework.security.core.Authentication
객체를 생성하여 사용자를 인증합니다.
인증 성공 시에는 위에서 생성된 해당 Authentication
객체를 반환하고 실패한 경우는 org.springframework.security.core.AuthenticationException
예외를 던집니다.
또한 ProviderManager
외에도 아래와 같은 AuthenticationManager
구현체가 존재합니다.
- DaoAuthenticationProvider: 데이터베이스에 접근하여 사용자의 인증 정보를 조회하고 비밀번호 인증을 지원하는 구현체입니다.
- RememberMeAuthenticationProvider:
org.springframework.security.authentication.RememberMeAuthenticationToken
의 유효성을 검사하는 구현체입니다.
Authentication Provider
AuthenticationProvider
는 사용자의 자격 증명(Certification)을 기반으로 인증하고 Authentication
객체를 생성하여 사용자 정보와 권한 정보를 제공합니다.AuthenticationProvider
를 구현받는 객체들은 supports(), authenticate()
메소드를 통해서 사용자의 Authentication
객체를 더 면밀한 평가할 수 있도록 지원합니다.
개발자들은 실제로 AuthenticationProvider
를 구현함으로써 폼 기반 인증, HTTP Basic 인증, OAuth 2.0, JWT 인증, LDAP 인증 등 다양한 메커니즘 구현할 수 있습니다.AuthenticationProvider
에서 생성된 인증 객체를 통해서 이후 Spring Security에서 인가 및 권한 검사에 사용됩니다.
Security Context
org.springframework.security.core.context.SecurityContext
는 현재 사용자의 인증, 권한 정보를 포함하고 있는 인스턴스로 스레드 로컬 변수(Thread-Local)에 저장됩니다.
즉 현재 실행 스레드와 관련된 최소 보안 정보를 정의하는 인터페이스입니다.
또한 정확히는 org.springframework.security.core.context.SecurityContextHolder
클래스가 스레드 로컬 변수에 SecurityContext
를 저장하여 관리하고 제어하는데 역활을 제공합니다.
즉 SecurityContextHolder
는 현재 스레드와 관련된 SecurityContext
를 관리하는데 사용되며 SecurityContext
는 현재 사용자의 보안 정보를 저장하는 객체입니다.
각각의 스레드가 자신만의 보안 컨텍스트를 가질 수 있으며 한 스레드에서 저장한 SecurityContext
정보는 다른 스레드에서 접근할 수 없습니다.
하지만 스레드 풀을 사용하는 환경에서 각 스레드에 SecurityContext
를 저장하면 스레드 풀의 크기에 따라 가용한 스레드의 수가 제한될 수 있습니다.
이를 방지하기 위해서 SecurityContextHolder
는 SecurityContext
를 어떻게 스레드에 연결할지 두 가지 다른 mode를 지원합니다.
- MODE_THREADLOCAL: 스레드에 대해 별도의
SecurityContext
인스턴스를 유지하며 스레드 간에SecurityContext
정보가 공유되지 않고 스레드 간에SecurityContext
를 격리하는데 사용됩니다. - MODE_INHERITABLETHREADLOCAL: 상속 가능한 스레드 로컬 변수(InheritableThreadLocal)에 저장합니다. 즉 부모 스레드에서 로그인한 사용자의
SecurityContext
가 자식 스레드에서도 사용될 수 있습니다. 다중 스레드를 사용하는 환경에서도 부모 스레드와 자식 스레드 간에 보안 컨텍스트를 상속할 수 있으나 스레드 간의SecurityContext
가 공유되므로 주의가 필요합니다.
오탈자 및 오류 내용을 댓글 또는 메일로 알려주시면, 검토 후 조치하겠습니다.
'Spring > Security' 카테고리의 다른 글
[Spring] Spring Security Authentication이란? (0) | 2023.12.10 |
---|---|
[Spring] Spring Security SecurityFilter란? (1) | 2023.12.03 |
[Spring] Spring Security 구성 요소 (0) | 2023.09.20 |