본문 바로가기
Spring/Spring Security

[Spring Security] SecurityContextHolder 내부구조와 PasswordEncoder

by yoon_seon 2023. 10. 28.

📌 SecurityContextHolder 내부구조

 

스프링 시큐리티는의 내부구조는 위 사진과 같이 서로 겹겹이 감싸고있다.

SecurityContextHolder -> SercurityContext -> Authentication -> Principal -> GrantAuthority

 

코드로 확인할 수 있음.

// SecurityContext에서 현재 사용자의 인증 및 보안 정보를 가져옵니다.
SecurityContext securityContext = SecurityContextHolder.getContext();

// 현재 사용자의 인증 정보를 가져옵니다.
Authentication authentication = securityContext.getAuthentication();

// 현재 사용자의 주체 (일반적으로 사용자 이름 또는 User 객체)를 반환합니다.
Object principal = authentication.getPrincipal();

// 현재 사용자가 부여받은 권한 목록을 반환합니다.
Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();

// 현재 사용자의 자격 증명 (패스워드 또는 기타 인증 정보)를 반환합니다.
Object credentials = authentication.getCredentials();

// 인증과 관련된 추가 세부 정보를 반환합니다.
Object details = authentication.getDetails();

// 현재 사용자가 인증되었는지 여부를 나타내는 부울 값을 반환합니다.
boolean isAuthenticated = authentication.isAuthenticated();

실제로 디버깅 걸어두면 확인 가능 

  • SecurityContextHolder
    SecurityContextHolder는 SecurityContext가 제공하는 getContext() 정적메서드를 통해서 context를 제공하고 있다
  • SecurityContext
    SecurityContext는 접근 주체와 인증에 대한 정보인 Authentication 정보를 담고있는 Context다.
  • Authentication
    SecurityContext는 접근 주체와 인증에 대한 정보인 Authentication 정보를 담고있는 Context다.
  • Principal
    유저에 해당하는 정보를 가지고 있으며 대부분 Principal로 UserDetails를 반환한다.
  • GrantAuthority
    ROLE_ADMIN, ROLE_USER등 Principal이 가지고 있는 권한을 나타낸다.
    prefix로 'ROLE_'이 붙는다.
    인증 이후 인가를 할 때 사용된다.
    권한은 여러개 일 수 있기 때문에 Collection<GrantedAuthrity> 형태로 제공한다.

 

SecurityContextHolder.getContext()로 독립적인 로그인 사용자의 인증 및 보안 정보를 가져올 수 있는 이유

SecurityContext securityContext = SecurityContextHolder.getContext(); 코드 한줄로 로그인 사용자의 인증 및 보안 정보를 가져올 수 있는 이유는 ThreadLocal 때문이다.

WebMVC 기반으로 프로젝트라는 가정하에 대부분의 경우 요청 1개에 Thread 1개가 생성되는데 이 때 ThreadLocal을 사용하면 Thread마다 고유한 영역이 생성되고 그곳에 SecurityContext를 저장할 수 있다. (요청 1개 : Thread 1개 : SecurityContext 1개)

따라서 ThreadLocal로 Spring Security를 관리하게 되면 SecurityContext는 요청마다 독립적으로 관리될 수 있는 것이다.

ThreadLocalSecurityContextHolderStrategy 클래스를 확인해보면 Spring Security의 기본 SecurityContext 관리 전략인 ThreadLocal을 사용하는 것을 알 수 있음.

SecurityContext 관리 전략은 총 3가지가 있다.

  • MODE_THREADLOCAL
    ThreadLocalSecurityContextHolderStrategy 사용. ThreadLocal을 사용하여 Thread 안에서 SecurityContext를 공유함.
  • MODE_INHERITABLETHREADLOCAL
    Inheritable ThreadLocalSecurityContextHolderStrategy 사용.Inheritable ThreadLocal을 사용하여 자식 Thread까지 SecurityContext를 공유함.
  • MODE_GLOBAL
    GlobalSecurityContextHolderStrategy 사용. 글로벌로 설정되어 어플리케이션 전체에서 SecurityContext를 공유함.

 


📌 PasswordEncoder

비밀번호 암호화는 보통 해시함수 알고리즘을 통해서 복호화가 불가능한 단방향으로 암호화한다.

 

PasswordEncoder 종류

  • NoOpPasswordEncoder
    • 암호화를 하지 않고 평문으로 사용한다.
    • password가 그대로 노출되기 때문에 현재는 deprecated 되었고 사용하지 않는 것을 권장
  • BcrptPasswordEncoder
    • Bcrypt 해시 함수를 사용한 PasswordEncoder
    • Bcrypt는 패스워드를 저장하기 위한 목적으로 설계되었음
    • Password를 무작위로 여러번 시도하여 맞추는 해킹을 방지하기 위해 암호를 확인할 때 의도적으로 느리게 설정되있다.
    • BcrptPasswordEncoder는 강도를 설정할 수 있으며 강도가 높을수록 오랜시간이 걸린다.
  • Pbkdf2PasswordEncoder
    • Pbkdf2는 NIST에 의해서 승인된 알고리즘이고, 미국 정부 시스템에서도 사용한다.
  • ScryptPasswordEncoder
    • Scrypt는 Pbkdf2와 유사하다.
    • 해커가 무작위로 passwordf를 맞추려고 시도할 때 메모리 사용량을 늘리거나 줄여서 느린 공격을 실행할 수 밖에 없도록 의도적인 방식을 사용한다. 따라서 공격이 매우 어렵고 Pbkdf2보다 안전하다고 평가받는다.
    • 보안에 아주 민감한 경우 사용할 수 있다.

댓글