본문 바로가기

Java

[Spring]SecurityContextHolder란?

반응형

SecurityContextHolder란?

  1. 기본적으로 ThreadLocal을 사용
    1. 한 쓰레드 내에서 사용하는 공용 저장소
    2. 쓰레드 내에서 Application을 공유 할수있다.
    3. SecurityContextHolder를 사용
    4. 쓰레드가 달라지면 제대로 된 인증 정보를 가져올 수 없음
  2. SecurityContextHodler는 싱글톤 객체
    1. SecurityContextHolder가 로드 될 때 한번 호출됩니다
      static { initialize(); }
  3. 해당 initialize 메소드에서 SecucirtyContextHolder에 대한 전략 방식을 파악
private static void initialize() {
        if (!StringUtils.hasText(strategyName)) {
            strategyName = "MODE_THREADLOCAL";
        }

        if (strategyName.equals("MODE_THREADLOCAL")) {
            strategy = new ThreadLocalSecurityContextHolderStrategy();
        } else if (strategyName.equals("MODE_INHERITABLETHREADLOCAL")) {
            strategy = new InheritableThreadLocalSecurityContextHolderStrategy();
        } else if (strategyName.equals("MODE_GLOBAL")) {
            strategy = new GlobalSecurityContextHolderStrategy();
        } else {
            try {
                Class<?> clazz = Class.forName(strategyName);
                Constructor<?> customStrategy = clazz.getConstructor();
                strategy = (SecurityContextHolderStrategy)customStrategy.newInstance();
            } catch (Exception var2) {
                ReflectionUtils.handleReflectionException(var2);
            }
        }

        ++initializeCount;
    }
  1. MODE_THERADLOCAL - 쓰레드별로 SecurityContext 관리
  2. MODE_INHERITABLETHREADLOCAL - 상위 쓰레드에서 하위 쓰레드로 Context 정보를 상속해줌
  3. MODE_GLOBAL - SecurityContext를 쓰레드 공용으로 관리
    1. SecurityContext 특성 상 Principal에 사용자 인증저보를 담고있으므로,
      보안 이슈가 있을 수 있음
    2. 성능저하
    3. JVM에서 제공하는 모든 스레드에서 같은 SecurityContext를 요구할때 사용
      Ex) Java Swing

의문점

  1. 왜 SecurityContext의 DeafultMode는 ThreadLocal인가?
    1. 사용자 정보가 담겨있는 주체이므로, 보안 상의 이유
    2. 성능 상 필요 없는 정보를 담고 있을 경우 느려질 수 있음
  2. 각 쓰레드별로 SecurityContext를 가져간다면 쓰레드 별 SecurityContext의 정확성 보장이 되는가?
    1. SecurityContext는 단순히 유저 인증정보를 담고있는 객체이므로, 관련 기능은 지원하지 않으며, 특수한 경우 추가 기능개발이 필요합니다.
  3. 이전에 로그인하여 SecurityContext의 사용자 계정이 로드되어 있다면, 어드민 계정에 의해
    권한이 변경되거나, 탈퇴처리 진행될 경우
    1. 위 사항과 동일한 부분이며, 즉각적인 처리가 필요한 사항이라면 관련 동기화 작업이 필요
  4. 쓰레드별로 SecurityContext가 관리된다면, 해당 유저가 어떤 쓰레드의 SecurityContext에서 관리되는지 어떻게 판단하는가
    1. 결론적으로는 SecurityContext의 역할이 아니다.
    2. Security 환경에서 Session을 사용할경우
    3. SecurityContext에서 인증 정보를 가져와서 Principal 객체를 추출합니다
      Authentication는 Principal 인터페이스 객체를 상속 받은 인터페이스입니다.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

해당 소스만 보았을 땐 이해가 어렵다.

클라이언트 요청에 알맞는 유저정보를 가져오는 법

  1. SecurityFilter에서 해당 Url 처리를 인터셉트함. (권한이 없을경우)
    1. 클라이언트 쿠키에 저장되어 있는 (예를들어 JSESSION) 값을 가져온 후 HttpServletRequest를 통해 해당 Session 키 값에 알맞는 HttpSession 반환
HttpSession session = request.getSession(false);
SecurityContext securityContext = (SecurityContext) session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
Authentication authentication = securityContext.getAuthentication();
  1. 위의 작업으로 인해 request.getSession(false)메소드 호출하였을때도 알맞는 HttpSession을 반환받을수 있음
    1. 이 부분은 세션 하이재킹 등 보안적 이슈로 직접적으로 인자 값을 넘기지 않음
  2. 해당 HttpSession에 저장되어 있는 SecurityContext를 반환받아, Authtication 객체를 가져올수있음.

위의 한줄짜리 Authentication에서 SecurityContextHolder.getContext()메소드 까지 호출되었을때 HttpSession에서 해당 SecurityContext를 가져온다는데, 나중에 확인 필요

반응형