
SecurityContextHolder에 대해 알아보자.
SecurityFilterChain 내부에 존재하는 각각의 필터가 시큐리티 관련 작업을 진행한다.
모든 작업은 기능 단위로 분업하여 진행하므로, 앞에서 진행했던 작업을 뒤에 있는 필터가 알기 위한 저장소 개념이 필요하다.
예를 들어 인가 필터가 작업을 하려면 유저의 Role 정보가 필요한데, 앞단의 필터에서 유저에게 부여한 Role 값이 인가 필터까지 공유되어야 이를 확인할 수 있다.

해당 정보는 Authentication이라는 객체에 담긴다. (아이디, 로그인 여부, ROLE 등)
Authentication 객체는 SecurityContext에 포함되어 관리되며 SecurityContext는 0개 이상 존재할 수 있다. 그리고 이 N개의 SecurityContext는 하나의 SecurityContextHolder에 의해서 관리된다.
// 접근
SecurityContextHolder.getContext().getAuthentication().getAuthorities();
SecurityContextHolder의 메소드는 static 으로 선언되기 때문에 어디서든 접근할 수 있다.
SecurityContextHolder.java
다수의 사용자인 멀티 쓰레드 환경에서 SecurityContextHolder를 통해 SecurityContext를 부여하는 관리 전략은 위임하여 다른 클래스에게 맡긴다.
(사용자별로 다른 저장소를 제공해야 인증 정보가 겹치는 일이 발생하지 않는다.)
즉, SecurityContextHolder는 SecurityContext들을 관리하는 메소드를 제공하지만, 실제로 등록, 초기화, 읽기와 같은 작업은 SecurityContextHolderStrategy 인터페이스를 활용한다.
SecurityContextHolder.java
THREADLOCAL, INHERITABLETHREADLOCAL, GLOBAL 방식이 존재한다
기본적으로 THREADLOCAL 방식을 사용한다.
ThreadLocalSecurityContextHolderStrategy.java
직접적으로 SecurityContext를 관리한다.
톰캣 WAS는 멀티 쓰레드 방식으로 동작한다. 유저가 접속하면 유저에게 하나의 쓰레드를 할당한다. 각각의 유저는 동시에 시큐리티 로그인 로직을 사용할 수 있다.
이때 SecurityContextHolder의 필드에 선언된 SecurityContext(static)를 호출하게 된다면 쓰레드 간 공유하는 메모리의 code 영역에 데이터가 있기 때문에 정보가 덮어지는 현상이 발생한다고 생각할 수 있는데, ThreadLocal로 관리되기 때문에 쓰레드별 다른 구획을 나눠 제공한다.

Authentication 객체를 관리하는 SecurityContext는 사용자의 요청이 서버로 들어오면 생성되고, 처리가 끝난 후 응답되는 순간에 초기화된다.