본문 바로가기
spring/security

SecurityContextHolder의 내부를 파헤쳐보자

by 참된오징어 2021. 5. 14.

인프런 백선장님의 강의를 보면서 내부가 좀 더 궁금해졌다.

 

# SecurityContextHolder란 ?


우선 강의에서 설명해주시는 정의는 다음과 같다.

 

1. 인증된 사용자 정보인 `Principal``Authentication`에서 관리하고
`Authentication``SecurityContext`가 관리하고
`SecurityContext``SecurityContextHolder`가 관리한다.

 

2. 기본적으로 ThreadLocal을 사용한다.

  • ThreadLocal : 한 쓰레드 내에서 사용하는 공용 저장소
  • 즉 ThreadLocal을 사용해서 `Authentication`을 한 쓰레드 내에서 공유가 가능하다.
  • 쓰레드가 달라지면 제대로 된 인증 정보를 가져올 수 없다.

즉 SecurityContextHolder란 Authentication를 담고 있는 Holder라고 정의를 할 수 있다.

 

`Authentication` 자체는 인증된 정보이기에 `SecurityContextHolder`가 가지고 있는 값을 통해

인증이 되었는지 아닌지 확인할 수 있다. [ Authentication.isAuthenticated(); ]

 

 

 

# SecurityContextHolder의 javadoc


이제 내부를 파헤쳐보자. (현재 버전은 5.4.2이다)
참고로 SecurityContextHolder의 소스는 길어봤자 200줄이 안 넘어서 내부를 쉽게 볼 수 있다.

 

시큐리티 의존성 버전

 

SecurityContextHolder 요 녀석은 위 의존성 중에 core 패키지에 포함되어 있다.

요 녀석의 javadoc을 해석해보자.

 

 

 

현재 실행 중인 스레드와 SecurityContext를 연결, 결합, 연관시킨다고 한다.

 

해당 클래스는 스태틱 메서드들을 제공하는데 어떤 스태틱 메서드들이냐면 
SecurityContextHolderStrategy의 인스턴스에 위임하는 스태틱 메서드들이라고 한다.

 

클래스의 목적은 주어진 JVM이 사용해야 하는 전략을 지정하는 편리한 방법을 제공하는 것이라고 한다.

이것은 JVM의 전체 세팅인데, 클래스의 모든 것이 호출하는 코드에서 쉽게 사용할 수 있도록 static이다.

사용될 전략을 지정하려면 모드 세팅을 제공해야 한다.

모드 세팅은 static final로 정의된 3가지 MODE_XXX 세팅 중 하나이거나

SecurityContextHolderStrategy 구현체를 파라미터가 없는 publc 생성자로 생성하는 것이다.

 

전략 모드를 지정하는 두 가지 방법이 있다.

1. SYSTEM_PROPERTY에 보관된 시스템 속성을 지정? 변경? 하는 것

2. 클래스를 사용하기 전에 setStrategyName(String)을 호출한다. (파라미터는 모드 세팅 값이다.)

두 가지 접근 모드 지정을 하지 않으면 기본적으로 MODE_THREADLOCAL을 사용한다.
(나머지 한 줄은 뭔 소린지 모르겠다.)

 

즉,

SecurityContextHolder라는 녀석은 쓰레드와 SecurityContext를 연결해주어 Authentication을 저장할 수 있는데

쓰레드가 달라지면 제대로 된 인증 정보를 가져올 수 없으니

런타임 시, SecurityContextHolderStrategy라는 인터페이스의 구현체들에게 쓰레드와 SecurityContext를

어떻게 연결시킬지에 대한 전략을 위임하며 런타임 시점에 static method를 통해서 어떤 방식의 전략인지 결정된다는 뜻 같다.

 

기본 값은 MODE_THREADLOCAL이며 다른 전략을 사용하고 싶으면 MODE를 변경하면 되며 두 가지 방법이 있다고 한다.

 

 

 

 

위에서 언급된 SecurityContextHolderStrategy는 무엇일까? 간단하게 알아보자.

 

# SecurityContextHolderStrategy


 

요 녀석도 SecurityContextHolder와 같은 패키지에 존재하며 javadoc 내용은 다음과 같다.

 

스레드에 대해서 SecurityContext 정보를 저장하는 전략이라고 한다.

기본 전략은 SecurityContextHolder에 의해 로드가 된다고 한다.

 

위에서 해석한 내용을 다시 확인해보면 SecurityContextHolder는 기본적으로 ThreadLocal을 사용하고 있으며

쓰레드가 달라지면 제대로 된 인증 정보를 가져올 수 없기에 이제 맞는 전략을 제공해주는 인터페이스라는 것을 파악!

그럼 다른 전략들은 무엇들이 있을까? 다음과 같이 3개의 전략이 있다.

 

  • GlobalSecurityContextHolderStrategy
  • InheritableThreadLocalSecurityContexyHolderStrategy
  • ThreadLocalSecurityContextHolderStrategy

SecurityContextHolderStrategy의 구현체들

 

 

 

# SecurityContextHolder의 내부 소스


서론이 너무 길었다. 내부 소스를 보자. 우선 상수부터 확인한다.

 

인스턴스 필드는 존재하지 않는다.

 

위 3개의 MODE_XXX는 javadoc에서 설명된 전략을 위한 모드 설정임을 알 수 있다.

 

MODE_THREADLOCAL

  • 현재 쓰레드에서만 사용 가능한 SecurityContext의 기본 모드

MODE_INHERITABLETHREADLOCAL

  • 현재 쓰레드에서 하위로 생성된 쓰레드에 SecurityContext를 공유하는 모드

MODE_GLOBAL

  • application의 모든 쓰레드에 SecurityContext를 공유 하는 모드

 

 

SYSTEM_PROPERTY, strategyName 또한 시스템 속성에 정의된 값으로 지정할 수 있다는 것을 이해할 수 있다.

 

SecurityContextHolderStrategy 타입의 정적 변수인 strategy는 static method에 의해 생성될 전략을 보관할 변수이며

 

initalizeCount 정수 변수는 전략을 초기화하는 카운트를 세는데, 주로 트러블 슈팅을 목적에 쓰인다고 한다. (method 설명에 쓰여있음)

 

다음으로 살펴볼 코드는 전략을 초기화하는 static 메서드이다.

 

 

static 블럭을 통해 초기화를 해주고 있으며 얼핏 봐도 strategyName이 무엇이냐에 따라 전략을 초기화해주는 메서드임을 확인할 수 있다. 그리고 메서드 마지막에는 초기화한 카운트를 증가시켜주고 있다.

현재 initialize() 메서드만 보면 접근 제한자가 private로 외부에서 접근이 제한된다.

한번 초기화된 전략을 바꾸고 싶으면 아래 사진과 같이 외부에 공개된 static setter 메서드를 사용하면 된다.

 

 

 

 


SecurityContextHolder의 내부를 보았고, 어떤 전략이 기본인지, 역할이 무엇인지 알아보았다.

이번에는 "언제" 인증된 정보인 Authentication을 SecurityContextHolder에 넣어주는지가 궁금해졌다.

다음 포스팅에는 SecurityContextHolder가 관리하는 SecurityContext 인터페이스와 구현체를 살펴보자.

댓글