Spring Security - 정수원 5일차

머어조·2022년 4월 5일

Spring Security

목록 보기
5/8

4. 인증 저장소 - SecurityContextHolder, SecurityContext

SecurityContext

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

SecurityContextHolder

  • SecurityContext 객체 저장 방식
    • MODE_THREADLOCAL : 스레드당 SecurityContext 객체를 할당, 기본값
    • MODE_INHERITABLETHREADLOCAL : 메인 쓰레드와 자식 스레드에 관하여 동일한 SecurityContext를 유지
    • MODE_GLOBAL : 응용프로그램에서 단 하나의 SecurityContext를 저장한다.
    • SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
  • SecurityContextHolder.clearContext() : Security 기존 정보 초기화

인증처리후

  • Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  • Authentication객체를 가져올 수 있다.
  1. 로그인 하면 서버에서 스레드하나 생성 (ThreadLocal에 저장)
  2. 인증 하려 하면 Authentication에 유저 정보 실어서 간다
  3. 그 와중 실패하면 SecurityContextHolder.clearContext() 로 해서 초기화 시킨다.
  4. 성공하면 SecurityContextHolder 안에 SecurityContext 안에 Authentication 인증 객체 담는다

결론

  • SecurityContextHolder 가 ThreadLocal객체를 가지고있고 ThreadLocal이 SecurityContext 를 담고있는다.
  • 최종적으로 HttpSession에 저장이 된다. ( SPRING_SECURITY_CONTEXT 라는 이름으로 )

5. 인증 저장소 필터 - SecurityContextPersistenceFilter

  • SecurityContext 객체의 생성, 저장 조회를 해준다.

  • 익명사용자

    • 새로운 SecurityContext 객체를 생성하여 SecurityContextHolder 에 저장
    • AnonymousAuthenticationFilter 에서 AnonymousAuthenticationToken 객체를 SecurityContext 에 저장
  • 인증 시 ( 인증 시점 )

    • 새로운 SecurityContext 객체를 생성하여 SecurityContextHolder 에 저장
    • UsernamePasswordAuthenticationFilter 에서 인증 성공 후 SecurityContext에 UsernamePasswordAuthenticationToekn 객체를 SecurityContext에 저장
    • 인증이 최종 완료되면 Session에 SecurityContext를 저장
  • 인증 후 ( 사용자가 인증 후 자원에 접근할 때 )

    • Session에서 SecurityContext 꺼내어 SecurityContextHolder 에서 저장
    • SecurityContext 안에 Authentication 객체가 존재하면 계속 인증을 유지
  • 최종 응답 시 공통 ( 익명사용자, 인증시, 인증후에서 응답할 때에 항상 )

    • SecurityContextHolder.clearContext() 호출

결론

  • SecurityContextPersistenceFilter는 SecurityContext 객체를 생성하여 SecurityContextHolder 에 저장하는 역할을 한다.
  • 수 많은 필터중 두번째로 실행된다.
  1. 사용자가 요청하면 어떤 요청이든 요청마다 SecurityContextPersistenceFilter 발동
  2. 내부적으로 HttpSecurityContextRepository 클래스가 SecurityContext 객체를 생성하고 조회하고 그런 역할을 하는 클래스이다.
  3. 인증전에 SecurityContextHolder 에 SecurityContext 객체를 생성한다.
  4. Form 인증 방식이면 UserPasswordAuthenticationFilter가 발동해서 인증 처리
  5. 인증필터에서 인증 성공하면 인증객체 저장
  6. 최종적으로 Session에 SecurityContextPersistenceFilter 가 저장한다
  7. Session에 저장 후 SecurityContextHolder.clearContext() 호출 해서 초기화 시킴
  8. 다시 요청을 하면 인증 후가 된다.
  9. 그래서 Session에 Security객체가 있는지 확인하고 꺼내서 저장한다.

정리

  • 인증 전에는 SecurityContext는 null, 인증 후에는 인증객체가있다. Session으로 부터 load 해온다.
  • 유저객체(UserDetails)는 Authentication에 저장되어있고, SecurityContext → ThreadLocal → SecurityContextHolder ㅇㅋ?

6. 인증 흐름 이해 - Authentication Flow

  1. client에서 로그인 요청이 들어오면
  2. UsernamePasswordAuthenticationFilter 가 발동, Authentication(id + password)객체에 인증 전 객체 토큰 저장 그리고 나서 AuthenticationManager에 인증 처리를 넘긴다.
  3. AuthenticationManager 는 인증의 전반적인 처리를 한다. 하지만 실제 인증 처리 역할을 하지않고 적절한 AuthenticationProvider에 위임한다.
  4. AuthenticationProvider 가 id 와 password가 맞는지 처리한다
  5. 유저 아이디(username)을 가지고 이 객체가 있는지 UserDetailService클래스에 요청한다.
  6. Repository에 유저 객체 정보 요청 있으면 가져오고 없으면 예외던짐(UsernamePasswordAuthenticationFilter 가 예외를 받는다 )
  7. 객체 정보가 있으면 UserDetail 타입으로 Provider에게 반환한다.
  8. Provider가 반환받은 객체와 로그인유저가 준 password를 비교해서 처리
  9. 성공 하면 Provider가 Authentication에 최종적으로 성공한 객체를 저장하고 반환 ( UserDetail + authorities) AuthenticationManager에게 전달
  10. UsernamePasswordAuthenticationFilter 가 최종적으로 반환받고 SecurityContext객체에 저장
profile
너어무 조오아

0개의 댓글