Notice
Recent Posts
Recent Comments
Link
«   2025/12   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Tags
more
Archives
Today
Total
관리 메뉴

기록하자..

스프링 시큐리티 - Servlet Authentication Architecture 본문

스프링 시큐리티

스프링 시큐리티 - Servlet Authentication Architecture

P23Yong 2022. 11. 8. 21:45

서블릿 인증 아키텍처

SecurityContextHolder

Spring Security의 인증 모델의 핵심은 SecurityContextHolder이다.
SecurityContextHolder는 이름에서도 알 수 있듯이 SecurityContext를 가지고 있다.

출처 Spring 공식문서

SecurityContextHolder는 어떤 사용자가 인증되었는지에 대한 정보들을 저장하고 있다. SpringSecurity는 이 SecurityContextHolder가 어떤 방식으로 채워지는지 알 수 없다. 만약 값을 가지고 있다면 현재 인증된 사용자를 가져올 수 있다.

SecurityContext context = SecurityContextHolder.createEmptyContext();  // 1
Authentication authentication = 
    new TestingAuthenticationToken("username", "password", "ROLE_USER"); // 2
context.setAuthentication(authentication);

SecurityContextHolder.setContext(context);  // 3
  1. SecurityContext 인스턴스를 생성한다.

    이떄 SecurityContextHolder.getContext().setAuthentication(authentication); 메서드를 사용할 수 있지만, 멀티 스레드 환경에서의 race condition을 피하기 위해 새로운 SecurityContext 인스턴스를 생성한다.
  2. Authentication 타입의 인스턴스를 생성한다.

    Spring Security는 어떤 Authentication의 구현체가 SecurityContext에 와도 상관이 없다.

    위에서는 TestingAuthenticationToken이라는 구현체를 사용하고 있다.
  3. 마지막으로 SecurityContextHolder에 위에서 생성한 SecurityContext를 넣는다.

SecurityContextHolder는 기본적으로 ThreadLocal을 사용해서 인증 정보를 저장한다.

이 떄문에 같은 스레드에서는 항상 같은 인증 정보로 접근이 가능하다.

이후에 인증정보가 겹치지 않게 요청 처리가 완료된 thread의 인증정보를 비워줘야 하는데 이는 SpringSecurity의 FilterChainProxy가 clear하도록 보장하고 있다.

SecurityContext

그러면 SecurityContext에 대해서 알아보자.

SecurityContext는 위의 사진에서도 알 수 있듯이 SecuityContextHolder에서 얻을 수 있고 Authentication 객체를 포함하고 있다.

코드는 다음과 같다.

public interface SecurityContext extends Serializable {

    Authentication getAuthentication();

    void setAuthentication(Authentication authentication);
}

getAuthenticationsetAuthentication 메서드를 통해 Authentication 정보를 가져오거나 설정할 수 있다.

Authentication

SecurityContext에서 얻을 수 있는 Authentication에 대해 알아보자.

Authentication은 인증된 사용자의 정보를 담고 있는 토큰과 같은 객체이다.

코드를 살펴보면,

public interface Authentication extends Principal, Serializable {

    Collection<? extends GrantedAuthority> getAuthorities();

    Object getCredentials();

    Object getPrincipal();

    Object getDetails();

    boolean isAuthenticated();

    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
  • authorities
    • 사용자의 권한 목록
  • principal
    • 사용자를 식별하는 객체 / Username과 Password를 가지고 인증할 때 UserDetails 인스턴스로 사용된다.
  • credential
    • 주로 사용자의 비밀번호이다.
  • details
    • 인증 부가 정보
  • authenticated
    • 인증 여부

AuthenticationManager

AuthenticationManager는 Spring Security의 필터들이 어떻게 authentication을 수행하게 할지 정의한 API이다.

반환된 AuthenticationAuthenticationManager에 의해 실행된 필터들에 의해 SecurityContextHolder에 들어간다.

public interface AuthenticationManager {

    Authentication authenticate(Authentication authentication) throws AuthenticationException;
}

일반적으로 AuthenticationManager의 구현체는 ProviderManager이다.

ProviderManager

위에서도 설명했듯이 ProviderManagerAuthenticationManager의 구현체이다.

특정 인증 유형을 확인할 수 있는 AuthenticationProvider 리스트를 가지고 있는데, ProviderManager는 이AuthenticationProvider 리스트에게 인증처리를 위임한다. 즉, AuthenticationProvider 목록 중 인증처리 조건에 맞는 적절한 Provider를 찾아 인증처리를 위임하는 클래스이다.

출처 Spring 공식문서

AuthenticationProvider

AuthenticationProvider는 다음과 같이 두 개의 메서드를 제공한다.

public interface AuthenticationProvider {

    Authentication authenticate(Authentication authentication) throws AuthenticationException;

    boolean supports(Class<?> authentication);

}
  • authenticate
    • 실질적인 인증 처리를 수행하는 메서드
  • supports
    • 인증 처리가 가능한 Provider인지 확인하는 메서드

예를 들어 DaoAuthenticationProvider는 username/password를 기반으로 인증과정을 수행한다.

참고 자료

Spring docs