Java/Spring

[Spring] Spring Security 동작 원리 파악 (id, pw 기반의 basic auth 방식)

SeungbeomKim 2024. 9. 6. 18:22

 

 

Spring Framwork 기반 Application에서 Spring Security를 적용하여 로그인 기능을 구현하곤 합니다. 기능 구현 방식에 있어, 전통적인 방식인 id, pw 기반의 세션 인증 방식이 있습니다.

 

오늘은 이 방식에 대해 상세히 정리해 보도록 하겠습니다. 이 포스팅은 Jwt, OAuth 기반의 인증에 대한 내용과는 별개의 내용이므로 참고 부탁드립니다.

 

우선 Spring Security의 개념과 관련 용어들에 대해 간단히 설명드리도록 하겠습니다.

 

Spring Security

  • Spring Security는 스프링 기반 애플리케이션의 보안을 담당하는 스프링 하위 프레임워크입니다.
  • 보안과 관련해서 체계적으로 많은 옵션들을 제공해 주기 때문에 개발자의 입장에서는 보안 관련 로직을 직접 작성하지 않아도 됩니다.

 

관련 용어

  • Authentication
    • 해당 사용자가 본인이 맞는지 확인하는 절차
  • Authorization
    • 인증된 사용자가 요청한 자원에 접근 가능한지를 결정하는 절차
  • Principal
    • 보호받는 Resource에 접근하는 대상
  • Credential
    • Resource에 접근하는 대상의 비밀번호
  • 권한
    • 인증된 주체가 애플리케이션의 동작을 수행할 수 있도록 허락되어 있는지를 결정
    • 인증 과정을 통해 주체가 증명된 이후 권한 부여
  • SecurityContextHolder
    • SecurityContext 객체를 저장하고 있는 wrapper 클래스
    • 보안 주체의 세부 정보를 포함하여 응용프로그램의 현재 보안 컨텍스트에 대한 세부 정보 저장
  • SecurityContextHolder class의 ThreadLocal 전략

  1. MODE_THREADLOCAL: default 설정 값, Thread당 SecurityContext 객체 할당
  2. MODE_INHERITABLETHREADLOCAL: 하위로 생성된 Thread에서 동일한 SecurityContext 객체 공유
  3. MODE_GLOBAL: Application의 모든 Thread가 단 하나의 SecurityContext만을 공유

 

  • SecurityContext
    • Authentication을 보관하는 역할
    • ThreadLocal에 저장되어 동일 스레드인 경우, 아무 곳에서나 참조가 가능합니다
      • ThreadLocal
        • 각각의 Thread별로 별도의 저장공간을 제공하는 컨테이너  
        • 하나의 Thread에서 실행되는 코드가 동일한 객체를 사용할 수 있도록 해주며, Thread와 관련된 코드에서 파라미터를 사용하지 않고, 객체를 전파하기 위한 용도로 사용됩니다.
    • 즉, SecurityContext는 ThreadLocal에 저장되어 있으면서, 동시에 HttpSession에도 저장되어 있습니다.
  • SecurityFilterChain
    • Spring Security는 표준 서블릿 필터를 기반으로 동작
    • SpringBoot의 기본 설정을 사용하는 경우, 인증에 사용되는 Filter들이 모여있는 SecurityFilterChain을 자동으로 등록해 주는데 SecurityFilterChain을 통해 스프링 시큐리티의 인증 과정이 동작하게 됩니다.
    • 이때 FilterChainProxy라는 클래스가 등장하는데, 해당 클래스는 DelegatingFilterProxy로부터 Filter 작동에 대한 요청을 위임받아 실제로 인증 처리를 하는 클래스입니다.
    • Spring Security를 사용하면 모든 요청은 FilterChainProxy 클래스를 거치게 되며, 내부에 getFilters() 메서드를 통해 SecurityFilterChain의 Filter 목록을 가져오게 됩니다.
  • SecurityContextPersistenceFilter
    • SecurityContext 객체의 생성, 조회, 저장 등의 LifeCycle을 담당하는 필터입니다.
    • 실제로는 SecurityContextRepository interface의 구현체인 HttpSessionSecurityContextRepository가 구현체로 사용되고 있습니다.

 

관련 용어와 SecurityContextHolder의 ThreadLocal 전략까지 알아보았으니, Spring Security 동작 흐름을 순차적으로 설명드리겠습니다.

 

Spring Security Authentication Architecture

  1. Client가 username, password 기반으로 HTTP 요청을 보냅니다
  2. Client로부터 HTTP 요청이 오면, 인증 및 권한 부여의 목적으로 일련의 필터를 거치게 됩니다. (Application Filter -> Authentication Filter..)
  3. AuthentcationFilter를 상속받은 UsernamePasswordAuthenticationFilter의 attemptAuthentication 메서드 내부에서 UsernamePasswordAuthenticationToken을 생성합니다
  4. 이후, AuthenticationManager interface의 구현체인 ProviderManager에게 UsernamePasswordAuthenticationToken 객체를 넘깁니다.
  5. ProviderManager는 AuthenticationProvider를 순회하면서 UsernamePasswordAuthenticationToken을 처리해 줄 AuthenticationProvider를 찾습니다.
  6. AuthenticationProvider interface의 구현체인 CustomAuthenticationProvider에서 인증 로직을 수행합니다.
  7. UserDetailsSerivce interface를 구현한 CustomUserDetailsService의 loadUserByUsername 메서드를 호출하여 세부 정보를 load합니다.
    • 근본적으로 DB에 있는 사용자 정보와 인증용 객체에 담긴 정보를 비교합니다.
    • 사용자 이름을 기반으로 UserDetails 객체를 반환하며, 이 객체는 인증 절차에서 사용됩니다.
  8. 인증절차를 통해 인증이 완료되면 Authentication 객체를 SecurityContextHolder 객체 안에 SecurityContext에 저장합니다.