Spring Security - 정수원 5일차

머어조·2022년 4월 5일
0

Spring Security

목록 보기
5/8
post-custom-banner

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 인증 객체 담는다

결론

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

5. 인증 저장소 필터 - SecurityContextPersistenceFilter

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

  • 익명사용자

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

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

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

    • SecurityContextHolder.clearContext() 호출

결론

  • SecurityContextPersistenceFilterSecurityContext 객체를 생성하여 SecurityContextHolder저장하는 역할을 한다.
  • 수 많은 필터중 두번째로 실행된다.
  1. 사용자가 요청하면 어떤 요청이든 요청마다 SecurityContextPersistenceFilter 발동
  2. 내부적으로 HttpSecurityContextRepository 클래스가 SecurityContext 객체를 생성하고 조회하고 그런 역할을 하는 클래스이다.
  3. 인증전에 SecurityContextHolderSecurityContext 객체를 생성한다.
  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
너어무 조오아
post-custom-banner

0개의 댓글