본문 바로가기
Study/Java

[TIL] Spring Security 인증

by hong- 2022. 7. 25.

🙌🏻 Spring Security 인증 처리


📍Authentication : 인증

 - 특정 리소스에 접근하려고 하는 사용자가 누구인지를 확인할 때 사용

     → 한 번 인증하면 사용자를 식별하고 권한을 부여할 수 있음 ( * 인가 : Authorization * )

 - 인터페이스로 존재하며 사용자가 인증을 성공적으로 수행하게 되면 사용자 인증 정보 관련 정보를 가짐

 ① principal : 사용자 식별

  - 사용자의 고유 식별자와 암호로 인증이 이루어지면 일반적으로 UserDetails 인터페이스의 구현체

  - 구현체로는 User클래스 or 직접 UserDetails를 상속받아 구현 가능

 ② credentials : 암호

   - 사용자의 인증이 이루어진 후 지워짐

 ③ Authorities : 인가에 대한 정보

  - AuthenticationManger에 의해 부여된 인가 정보

  - 부여된 권한에 대한 정보는 GrantedAuthority로 추상화

  * UsernamePasswordAuthenticationToken

  - 사용자의 고유 식별자와 암호로 간단하게 Authentication 객체를 생성할 수 있음


 💡 Spring Security

  - 사용자 인증 처리를 기본으로 제공

  - 종합적인 인증 처리를 지원함


📍Password Storage

  ▪️ PasswordEncoder

   - 스프링 시큐리티의 PasswordEncoder 인터페이스는 비밀번호를 안전하게 저장할 수 있도록 단방향 변환 수행

   - PasswordEncoder은 비밀번호를 단방향으로 변환

   - 인증에 사용할 credential 정보를 저장함

   - 인증 시점에 사용자가 입력하는 비밀번호와 비교하는 용도로 쓰임


📍Servlet Authentication Architecture : 서블릿 인증 구조

  ▪️ Architecture

  ① SecurityContextHolder

   - 스프링 시큐리티에서 인증한 대상에 대한 상세 정보 조회를 저장함

SecurityContext context = SecurityContext.Holder.createEmptyContext( );
Authentication authentication
       = new TestingAuthenticationToken("username", "password", "ROLE_USER");
context.setAuthentication(authentication);

SecurityContextHolder.setContext(context);

 (1) 빈 Security Context를 만들어 시작

 (2) 새로운 Authentication 객체를 생성하고 Authentication 구현체를 모두 사용 가능

   - 프로덕션 환경에서는 TestingAuthenticationToken 대신 UsernamePasswordAuthenticationToken 주로 사용

 (3) Security Context Holder에 Security Context를 설정해주고 스프링 시큐리티는 이 정보를 사용해 권한 인가

 

 → Authentication에 토큰을 설정하고 context에 넣어준 후 contextHolder에 넣어줌


  ② SecurityContext

   - Security Context Holder 로 접근하는데 사용

   - 인증한 사용자의 Authentication을 가짐


  ③ Authentication

   - 사용자가 인증을 위해 제공한 자격 증명이나 Security Context에 있는 현재 사용자의 자격 증명을 제공

   - Authentication Manager의 입력으로 사용

  * Authentication이 가지고 있는 정보들 *

   1) Principal 

    - 사용자를 식별하는 정보

    - 사용자 이름 / 비밀번호로 인증할 땐 보통 UserDetails 인스턴스를 이용

   2) credentials

    - 일반적으로 비밀번호 사용

   3) authorities

    - 사용자에게 부여한 권한은 grantedAuthority로 추상화


  ④ GrantedAuthority

   - Authentication에서 접근 주체에 부여한 권한이자 애플리케이션 전체에 걸친 권한

   - 사용자에게 부여한 권한을 추상화 

   - role과 scope이 있음

   - Authentication.getAuthorities( )로 접근할 수 있음 → GrantedAuthority 객체의 Collection 리턴

   - 권한은 보통 role=역할을 의미하고 웹 인가, 메서드 인가, 도메인 객체 인가 등에서 사용

   - 이름/비밀번호 기반 인증을 사용한다면 UserDetailsService가 GrantedAuthority를 로드함


  ⑤ AuthenticationManager

   - 스프링 시큐리티의 필터가 인증을 어떻게 수행하는지에 대한 방법을 정의한 API

   - AuthenticationManager를 호출한 객체(=필터)가 리턴한 Authentication을 SecurityContextHolder에 설정

      → Filters를 사용하지 않으면 SecurityContextHolder에 직접 설정


  ⑥ ProviderManager

   - 가장 많이 사용하는 Authentication Manager 구현체

   - Provider Manager는 동작을 AuthenticationProvider List에 위임

     → 모든 Authentication Provider은 인증을 성공 or 실패 or 결정을 내릴 수 없는 것으로 판단하여

         다운스트림에 있는 Authentication Provider이 결정할 수 있도록 만들 수 있음

     → 설정해 둔 Authentication Provider이 모두 인증을 실패하면 ProviderNotFoundException 예외 발생


   ⑦ AuthenticationProvider

   - Provider Manager가 특정 인증 유형을 수행할 때 사용

   - 각 Provider은 각자 맡은 인증을 수행함 = 담당하는 인증 유형이 다름

     → DaoAuthenticationProvider은 이름/비밀번호 기반 인증 지원

     → JwtAuthenticationProvider은 JWT 토큰 인증 지원

   - 각 구현체의 authenticate( )에서 정의된 특정 유형에 따른 인증 수행  

   - ProviderManager에 AuthenticationProvider를 여러 개 주입할 수 있음


  ⑧ Request Credentials with AuthenticationEntryPoint

   - 클라이언트가 Credential(자격 증명)을 요청할 때 사용


  ⑨ AbstractAuthenticationProcessingFilter

  - 인증에 사용할 Filter의 베이스

  - 여러 컴포넌트를 조합해서 심도 있는 인증 플로우를 구성할 수 있음


📍SecurityContextPersistenceFilter

  - SecurityContext 객체를 영속화하는 역할을 수행하는 필터

  - SecurityContextRepsitory라는 SecurityContext 저장소 객체를 보유

     → 해당 저장소 객체를 통해 SecurityContext를 영속화하고 기존에 저장된 SecurityContext 객체를

         꺼내어 SecurityContextHolder에 저장하는 등의 역할 수행

 💡 SecurityContext

  - 객체의 생성, 저장, 조회 등의 라이프사이클을 담당하는 필터

  - SecurityContextRepository를 가지고 있음

 💡 SecurityContextRepository

  - SecurityContext를 Persist하기 위한 구현체


  ▪️ SecurityContextPersistenceFilter 처리 순서

  ① 클라이언트 요청이 발생

  ② SecurityContextRepository 인터페이스의 loadContext( )로 저장된 SecurityContext 객체를 가져옴

     - 기본으로 사용되는 저장소는 HttpSessionSecurityRepository이며 HttpSession에 SecurityContext를 저장

  ③ 해당 클라이언트의 요청이 모두 수행된 후 기존에 저장했던 SecurityContextHolder의 clearContext( )로 SecurityContext 제거

  ④ SecurityContextRepository에 해당 SecurityContext를 다시 저장


▪️ SecurityContext 객체의 생성, 저장, 조회

 ▸ 익명 사용자

  - 새로운 SecurityContext 객체를 생성하여 SecurityContextHolder에 저장

  - AnonymouseAuthenticationFilter에서 AnonymouseAuthenticationToken객체를 SecurityContext에 저장

 ▸ 인증 시

  - 새로운 SecurityContext 객체를 생성하여 SecurityContextHolder에 저장

  - UsernamePasswordAuthenticationFilter에서 인증 성공 후 SecurityContext에

     UsernanePasswordAuthentication 객체를 SecurityContext에 저장

  - 인증이 최종 완료되면 Session에 SecurityContext를 저장

 ▸ 인증 후

  - Session에서 SecurityContext를 꺼낸 후 SecurityContextHolder에서 저장

  - SecurityContext안에 Authentication 객체가 존재하면 계속 인증 유지

 ▸ 최종 응답 시 공통

  - SecurityContextHolder안의 SecurityContext 객체에서 보관하던 인증 정보를 반드시 초기화

  - SecurityContextHolder.clearContext()를 호출하여 인증 정보 초기화


 

'Study > Java' 카테고리의 다른 글

[TIL] Spring Security 인가  (0) 2022.07.26
[TIL] Filter vs Interceptor  (0) 2022.07.25
[TIL] Spring Security  (0) 2022.07.24
[TIL] API 문서화  (0) 2022.07.21
[TIL] 인증/보안  (0) 2022.07.21