스프링 시큐리티 - Authentication, SecurityContext

SeungTaek·2022년 2월 21일
2
post-thumbnail

본 게시물은 스스로의 공부를 위한 글입니다.
잘못된 내용이 있으면 댓글로 알려주세요!

Authentication(인증 객체)

사용자의 인증 정보를 저장하는 토큰 개념.

2가지 용도로 사용된다. 인증 용도 또는 인증 후 세션에 담기 위한 용도

  1. 인증시 id와 password를 담고 인증 검증을 위해 전달되어 사용된다.

  2. 인증 후 최종 인증 결과(user 객체, 권한 정보)를 담고 SecurityContext에 저장되어 아래와 같은 코드로 전역적으로 참조가 가능하다.

Authentication authentication = SecurityContexHolder.getContext().getAuthentication()


Authentication 구조

  1. Principal(Object 타입): 사용자 아이디 혹은 User 객체를 저장
  2. Credentials: 사용자 비밀번호
  3. authorities: 인증된 사용자의 권한 목록
  4. details: 인증 부과 정보
  5. Authenticated: 인증 여부

Authentication은 인터페이스이므로 구현체가 따로 존재한다. 물론 사용자가 직접 커스텀도 가능하다. 대표적으로 UsernamepPasswordAuthenticationFilter이 있다.


details을 set할 때에 authenticationDetailsSource.buildDetails(request)가 호출된다. 리턴타입은 WebAuthenticationDetails 객체이다.
기본적으로 remoteAddress, SessionId 등 인증 과정 중 전달된 데이터를 객체에 담게된다. 물론 extends 후 커스텀 가능하다.

protected void setDetails(HttpServletRequest request, UsernamePasswordAuthenticationToken authRequest) {
        authRequest.setDetails(this.authenticationDetailsSource.buildDetails(request));
}



SecurityContext

  • Authentication 객체가 저장되는 보관소로 필요 시 언제든지 Authentication 객체를 꺼내어 쓸 수 있도록 제공되는 클래스
  • ThreadLocal에 저장되어 아무 곳에서나 참조가 가능하도록 설계함
  • 인증이 완료되면 HttpSession에 저장되어 어플리케이션 전반에 걸쳐 전역적인 참조가 가능하다.

SecurityContextHolder

  • SecurityContext 객체 저장 방식
    • MODE_THREADLOCAL: 스레드당 SecurityContext 객체를 할당, 기본값
      • 자식 쓰레드와는 공유가 되지 않는다. 공유를 하려면 아래 모드로 변환을 해야한다.
    • MODE_INHERITABLETHREADLOCAL: 메인 스레드와 자식 스레드에 관하여 동일한 SecurityContext를 유지
    • MODE_GLOBAL: 응용 프로그램에서 단 하나의 SecurityContext를 저장한다.
  • 객체 저장 방식은 보안 설정 클래스에서 변경할 수 있다.(앱 기동시 초기화)
    SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL)
  • SecurityContextHolder.clearContext(): SecurityContext 기존 정보 초기화하는 코드이다.

어차피 SecurityContext가 세션에 저장되기 때문에 세션->SecurityContext-> 인증객체를 찾아도 괜찮다.

@GetMapping()
public String index(HttpSession session){
  Authentication authentication1 = SecurityContextHolder.getContext().getAuthentication()
  
  SecurityContext context = (SecurityContext)session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
  Authenticatino authentication2 = context.getAuthentication();
  
  // authentication1 == authentication2 이다.
}


SecurityContextPersistenceFilter

SecurityContext 객체의 생성, 저장, 조회하는 필터이다.

  1. 익명 사용자
  • 새로운 SecurityContext 객체를 생성하여 SecurityContextHolder에 저장한다.
  • AnonmousAuthenticationFilter에서 AnonymousAuthenticationToken 객체를 SecurityContext에 저장한다.

  1. 인증 시
  • 새로운 SecurityContext 객체를 생성하여 SecurityContextHolder에 저장
  • UsernamePasswordAuthenticationFilter에서 인증 성공 후 UsernamePasswordAuthenticationToken 객체를 SecurityContext에 저장한다.
  • 인증이 최종 완료되면 Session에 SecurityContext를 저장한다.

  1. 인증 후
  • Session에서 SecurityContext를 꺼내에 SecurityContextHolder에 저장한다.
  • SecurityContext 안에 Authentication 객체가 존재하면 계속 인증을 유지한다.

  1. 최종 응답 시 공통
  • SecurityContextHolder.clearContext()



Reference

인프런 '스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security' (정수원)

profile
I Think So!

2개의 댓글

comment-user-thumbnail
2024년 10월 11일

안녕하세요! 글 잘 봤습니다. 덕분에 코드를 이해하는데 도움이 됬습니다. 혹시 어떤 자료를 통해 공부하셨는지 알수 있을 까요?

1개의 답글