본문 바로가기
Spring/Security

[Spring] Spring Security란?

by 기몬식 2023. 9. 14.

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 를 저장하면 스레드 풀의 크기에 따라 가용한 스레드의 수가 제한될 수 있습니다.
이를 방지하기 위해서 SecurityContextHolderSecurityContext 를 어떻게 스레드에 연결할지 두 가지 다른 mode를 지원합니다.

  • MODE_THREADLOCAL: 스레드에 대해 별도의 SecurityContext 인스턴스를 유지하며 스레드 간에 SecurityContext 정보가 공유되지 않고 스레드 간에 SecurityContext 를 격리하는데 사용됩니다.
  • MODE_INHERITABLETHREADLOCAL: 상속 가능한 스레드 로컬 변수(InheritableThreadLocal)에 저장합니다. 즉 부모 스레드에서 로그인한 사용자의 SecurityContext 가 자식 스레드에서도 사용될 수 있습니다. 다중 스레드를 사용하는 환경에서도 부모 스레드와 자식 스레드 간에 보안 컨텍스트를 상속할 수 있으나 스레드 간의 SecurityContext가 공유되므로 주의가 필요합니다.

오탈자 및 오류 내용을 댓글 또는 메일로 알려주시면, 검토 후 조치하겠습니다.