모놀리식 구조의 서비스를 MSA로 전환하는 프로젝트를 진행하면서 로그인되어 있는 회원의 정보를 인식할 수 없는 상황이 발생했다.
기존 로그인 회원 정보 조회 코드
@Slf4j
public class SecurityUtil {
private SecurityUtil() { }
// SecurityContext 에 유저 정보가 저장되는 시점
// Request 가 들어올 때 JwtFilter 의 doFilter 에서 저장
public static Long getCurrentMemberId() throws NumberFormatException{
final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (authentication == null || authentication.getName() == null) {
throw new CustomException(INVALID_ACCESS_TOKEN);
}
return Long.parseLong(authentication.getName());
}
}
회원 로그인 시 Access Token 검증 후 SecurityContextHolder -> SecurityContext -> Authentication에 인증 정보(Principal, Credentials, Authorities)를 저장한다.
출처: https://gregor77.github.io/2021/04/19/spring-security-01/
따라서 SecurityContextHolder에 저장되어 있는 로그인 회원 정보를 조회하여 프론트 서버로부터 회원 ID를 요청받지 않아도 회원 정보를 조회할 수 있다.
하지만 SecurityContextHolder는 기본적으로 Thread-Local 영역에 저장되어 다른 서비스(서버)에서 호출 시 로그인 정보를 얻을 수 없어 anonymousUser 즉, 익명 사용자로 인식하게 된다.
SecurityContextHolder Strategy
SecurityContextHolder는 3가지의 전략(Strategy)를 제공한다.
- MODE_THREADLOCAL : thread 내부에서 사용되는 지역변수인 thread-local 변수로 thread 수준에서 공유하는 데이터 수준
- MODE_INHERITABLETHREADLOCAL : 현재 스레드에서 하위에 생성 된 스레드까지 SecurityContext 공유
- MODE_GLOBAL : 애플리케이션 전체에서 SecurityContext 공유
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_GLOBAL);
MODE_GLOBAL은 GlobalSecurityContextHolderStrategy 클래스를 구현체로 사용한다.
static 선언하여 SecurityContext를 저장하는 해당 전략은 JVM 내의 모든 인스턴스들은 공유할 수 있지만, 해당 애플리케이션에 국한되어 역시 서버 간의 한계를 넘지 못한다.
JWT 복호화
Request Header의 Access Token을 복호화하여 현재 로그인한 회원 정보를 조회한다.
jwt의 getSubject값으로 memberId를 얻을 수 있다. 이 때의 memberId는 UserDetailsService의 loadUserByUsername에서 return하는 UserDetails값에 세팅한 memberId값이다.
즉, Client로부터 요청된 request header의 token을 조회하여 서버 간의 통신 없이 로그인 한 회원의 정보를 알 수 있다.
물론, 복호화하려는 서버에는 token secret값을 가지고 있어야 한다.
application.yml
token:
secret: ...
'Spring' 카테고리의 다른 글
Spring Cloud Config URL 조회 시 보안 (0) | 2023.11.04 |
---|---|
Embedded Redis로 테스트 환경 구축하기 (0) | 2023.10.30 |
Spring Cloud Config Watch (1) | 2023.10.11 |
Spring Gateway 에러 핸들링 (0) | 2023.09.19 |
Spring MVC DispatcherServlet 분석 (0) | 2023.07.27 |