본문 바로가기
Spring

Spring / Security란?

by LWM 2020. 8. 2.
반응형

스프링 시큐리티란?

스프링 시큐리티는 인증, 인가, 일반적인 공격에 대한 보호를 제공하는 프레임워크이다.

시큐리티는 인증과 인가를 분리하여 아키텍쳐가 설계되어 있는데, 해당 포스트에서는 아키텍쳐와 인증 프로세스 그리고 인증 프로세스에서 사용되는 주요 컴포넌트에 대해 살펴보겠다.

 

 

 

인증

인증이란 컴퓨터 시스템 사용자의 신원(주소, 신분 등)같은 주장을 증명하는 행위이다.

사람 또는 사물의 신원을 나타내는 행위와 대조적으로 인증은 그 신원을 검증하는 프로세스이다. 

즉, 인증이란 사용자 이름, 사용자 아이디, 사용자 패스워드 등과 같은 자격을 증명하는 것을 검사하여 신분을 검증하는 것이다. 그렇다면 어떻게 스프링에서 시큐리티가 동작하는지 다음과 같은 시나리오와 함께 살펴보자.

 

-시나리오-

  1. 사용자 이름과 암호를 입력받는다.
  2. 사용자 이름과 암호가 올바른지 확인한다
  3. 인증이 완료되었다
  4. 사용자가 가진 권한 내에서 작업을 수행할 수 있다.

 

-스프링 내부 프로세스 흐름-

  1. 사용자의 이름과 암호를 입력받아 Authentication의 구현체인 UsernamePasswordAuthenticationToken객체를 만든다.
  2. 만들어진 토큰을 AuthenticationManager로 전달한다.
  3. AuthenticationManager를 통해 전달받은 토큰으로 사용자를 인증한다.

    - 사용자 인증에 성공하면 인가에 필요한 정보(권한, ROLE 등) 등을 주입한 Authentication(보통 #isAuthenticated()가 true를 반환)을 반환한다.

    - 입력된 암호와 패스워드 등을 신뢰할 수 없거나 유효하지 못하면 AuthenticationException을 발생시킨다.

    - 인증을 결정하지 못하면(예를 들어 지원하는 Authentication의 구현체가 아닐 경우) null을 반환한다.
  4. AuthenticationManager가 반환한 Authentication을 SecurityContextHolder를 통해 SecurityContext에 넣는다.
    (이 시점에서 인증이 완료된것이다.)
  5. 이후 SecurityContextHolder에 있는 Authentication에 부여된 권한 범위내에서 작업을 수행할 수 있다.
    (여기부터는 인가의 영역이다.)

위와 같은 security 흐름은 보통 security interceptor에서 이루어지는데 사용자가 직접 작성하여 커스터마이징 할 수도 있다. 웹에서 위와 같은 프로세스 흐름을 스프링 시큐리티의 필터와 인터셉터가 처리해준다는 것을 기억하자.

 

또 하나 기억할 것은 SecurityContext에 Authentication이 들어가는 과정 자체는 스프링 시큐리티가 신경쓰지않으며, 이를 이용해 제 3자가 제공하는 인증시스템과 상호운영할 수 있다. 

 

 

 

 

인증 프로세스에서 사용되는 주요 컴포넌트

- Authentication

Authentication인터페이스는 개인, 회사, 로그인 ID와 같은 객체의 추상 개념이다.

사용자의 이름과 비밀번호등을 가지고 있는 UsernamePasswordAuthenticationToken은 Authentication인터페이스의 구현체이다. Authentication#getAuthorities()를 통해 해당 객체의 권한을 확인 할 수 있다.

 

- AuthenticationManager (ProviderManager and AuthenticationProvider)

Authentication은 스프링 시큐리티에서 제공하는 인증에서의 핵심 인터페이스이다.

public interface AuthenticationManager {

  Authentication authenticate(Authentication authentication)
    throws AuthenticationException;

}

스프링 시큐리티에서는 AuthenticationManager의 구현체인 ProviderManager를 제공한다.

ProviderManager는 인증 요청(Authentication 객체)을 받아 AuthenticationProvider 리스트에 요청을 전달한다. AuthenticationProvider의 support()메서드를 통해 지원하는 인증(Authentication 구현체)인지 확인하고 인증(실제 유저 아이디가 존재하는지, 또는 패스워드가 일치하는지)을 한다.

지원하지 않는 Authentication을 전달받으면 null을 반환하는데 만약 모든 AuthenticationProvider에서 null을 반환하면 ProviderNotFoundException이 발생한다.

애플리케이션은 보호하는 리소스를 논리적인 그룹(웹에서는 /api/** 와 같은 패턴)으로 묶는다.

각 그룹은 고유의 AuthenticationManager를 가지며, ProviderManager는 선택적으로 부모가 존재한다.

그리고 가끔 ProviderManager는 부모를 공유하는데, 그러면 부모는 일종의 global 리소스가 되어 모든 AuthenticationPorvider의 폴백(2번째 계획, 처음 실패했을 시의 대안) 역할을 한다.

- SecurityContext

SecurityContext는 현재 스레드(SecurityContextHolder에 설정된 전략에 따라 달라짐)에 연관된 최소한의 보안정보를 정의하는 인터페이스이다. SecurityContextHolder는 SecurityContextHolder에 저장된다.

 

- SecurityContextHolder

SecurityContextHolder는 현재 응용 프로그램에서 사용하는 보안 주체(principal)의 세부 정보가 포함된 SecurityContext를 저장하고 공유한다. SecurityContext를 공유하는 방법 3가지 모드는 다음과 같다.

  • MODE_THREADLOCAL(기본값): 같은 스레드에서 공유
  • MODE_INHERITABLETHREADLOCAL: 같은 스레드와 자식 스레드까지 공유
  • MODE_GLOBAL: static하게 공유

SecurityContextHolder의 모드를 커스터마이징, 사용하는 모드를 변경할 수 있는데 생성자가 없는 SecurityContextHolderStrategy의 서브클래스를 구현하고, 시스템 프로퍼티, 혹은 setStrategyName()을 하고 initialize()로 모드를 설정할 수 있다.

또한 SecurityContextHolder를 사용하기 전 #setStrategyName()을 통해 전략을 설정할 수 있는데, 사용 중일 경우 #clearContext()를 사용하고 #setStrategyName()을 사용하거나 시스템 환경변수를 설정하면 된다.

반응형

'Spring' 카테고리의 다른 글

Spring / 퍼시스턴스 프레임워크  (0) 2020.09.22
Spring / Filter와 Interceptor  (0) 2020.07.10
Spring / AOP란?  (0) 2020.07.10
Spring / IoC와 DI  (0) 2020.07.10
Spring / Spring이란?  (0) 2020.07.10