본문 바로가기
spring/security

AutenticationManger, ProviderManger, AuthenticationProvider를 알아보자.

by 참된오징어 2021. 5. 24.

이번엔 인증처리를 하는 주요 객체를 간단하게 살펴보자.

 

 

 

# AuthenticationManager

 

AuthenticationManager is the API that defines how Spring Security’s Filters perform authentication. The Authentication that is returned is then set on the SecurityContextHolder by the controller (i.e. Spring Security’s Filterss) that invoked the AuthenticationManager.

 

If you are not integrating with Spring Security’s Filterss you can set the SecurityContextHolder directly and are not required to use an AuthenticationManager.

While the implementation of AuthenticationManager could be anything, the most common implementation is ProviderManager.

 

먼저 스프링 문서에서 설명된 내용을 해석해보면

 

AuthenticationManager는 스프링 시큐리티 필터들이 수행하는 방식을 정의한 API라고 한다.

AuthenticationManager가 리턴한 Authentication 객체를 SecurityContextHolder에 설정하는 녀석은

AuthenticationManager를 호출한 시큐리티 필터가 담당한다.

 

만약 당신이 스프링 시큐리티의 필터를 통합? 사용? 하지 않는다면 당신은 직접적으로 SecurityContextHolder에 설정하면 된다 AuthenticationManager를 사용할 필요없이.

AuthenticationManager의 구현체를 어떤 것이든 사용해도 좋지만, 가장 흔한 구현체는 ProviderManager이다. 

 

 

강의에서도 설명되었듯이 AuthenticationManager를 호출하는 녀석들은 시큐리티 필터들인데

시큐리티 필터 내에서 요청으로 넘어온 인증 정보를 Authentication 객체로 만들고 AuthenticaionManager에게 인증 처리를 위임한다.

 

UsernamePasswordSecurityFilter 의 attemptAuthentication() 메서드 내부

UsernamePasswordSecurityFilter의 내부에서 인증시 실제로 AuthenticationManager에게 인증 처리를 위임하고 있음을 확인할 수 있다. (UsernamePassowordAuthenticationToken은 Authentication 인터페이스의 구현체이다)

 

AuthenticationManager 인터페이스는 다음과 같다.

이전 포스팅에도 설명되었듯이 파라미터는 아직 인증되지 않은 정보이며, 반환값은 인증된 정보이다.

 

위 자바 doc에서 설명되었듯이 AuthenticationManager의 구현체는 ProviderManager가 있다.

ProviderManager도 살펴보자.

 

 

 

 

 

# ProviderManager

스프링 문서에서 설명된 내용을 해석해보면

 

ProviderManager is the most commonly used implementation of AuthenticationManager. ProviderManager delegates to a List of AuthenticationProviders. Each AuthenticationProvider has an opportunity to indicate that authentication should be successful, fail, or indicate it cannot make a decision and allow a downstream AuthenticationProvider to decide.

If none of the configured AuthenticationProviders can authenticate, then authentication will fail with a ProviderNotFoundException which is a special AuthenticationException that indicates the ProviderManager was not configured to support the type of Authentication that was passed into it.

 

ProvierManager는 가장 많이 사용하는 AuthenticationManager의 구현체이다.

ProvierManager는 AuthenticationProvider List에게 위임한다.

 AuthenticationProvider는 인증을 성공시키거나, 실패시키거나, 결정을 내릴 수 없거나 다운스트림에 있는 AuthenticationProvider가 결정하도록 만들 수 있는 기회가 주어진다.

 

만약 설정해두었던 AuthenticationProvider들이 인증을 하지 못한다면, ProviderNotFoundException이 발생하면서 인증이 실패하게 되는데, 이 ProviderNotFoundException은 AuthenticationException의 하위 클래스로, 인증을 통과하는 ProviderManager를 설정하지 못해서 발생하는 예외이다.

 

결국 AuthenticationManager의 구현체인 ProvierManager가 인증을 처리하는데

실제로 ProvierManager 얘도 내부에 가지고 있는 AuthenticationProvider 들에게 인증 처리를 위임하는 녀석이다.

 

더 해석해보자.

 

In practice each AuthenticationProvider knows how to perform a specific type of authentication. For example, one AuthenticationProvider might be able to validate a username/password, while another might be able to authenticate a SAML assertion. This allows each AuthenticationProvider to do a very specific type of authentication, while supporting multiple types of authentication and only exposing a single AuthenticationManager bean.

 

ProviderManager also allows configuring an optional parent AuthenticationManager which is consulted in the event that no AuthenticationProvider can perform authentication. The parent can be any type of AuthenticationManager, but it is often an instance of ProviderManager.

 

각 AuthenticationProvider들은 어떻게 인증을 수행할지 알고있다.

예를 들어, 하나의 AuthenticationProvider가 이름과 비밀번호를 검증할 수 있으면, 다른 Provider는 SAML 인증을 할 수 있다.

각 AuthenticationProvider 마다 구체적인 인증 방법이 허락되어 있어서 AuthenticationManager 빈 하나만 외부에

노출하면 여러 인증 유형을 지원할 수 있다.

 

ProviderManager는 인증을 수행할 수 있는 AuthenticationProvider가 없는 상황이 있다면

부모 AuthenticationManager을 선택적으로 설정할 수 있도록 허용한다.

부모는 AuthenticationManager의 어떤 구현체가 될 수 있지만 ProviderManager의 인스턴스를 종종 사용한다.

 

추가로 더 설명된 문서의 내용을 해석하진 않았는데, 

해당 내용은 ProviderManager가 인증에 성공하면 Authentication 객체의 Credential 정보를 지운다는 내용이다. 참고만 하자.

 

ProviderManager 내부를 살펴보면

 

실제 인증을 처리하는 AuthenticationProvider들을 리스트로 가지고 있고, 생성시 주입을 받는다.

그리도 문서에서 설명되었듯이 AuthenticationManager을 주입받아 설정할 수 있도록 지원하고 있다.

 

 

ProviderManager에서 눈 여겨 볼 것은 인증하는 메서드에서
갖고있는 프로바이더들이 해당 인증을 할 수 있는지 찾고 인증할 수 있는 프로바이더가 있으면 인증을 위임하고 없으면 예외를 발생한다.

(사진에는 없지만 메서드 마지막에 throw lastException; 을 수행하고 있다.)

 

 

 

마자믹으로 AuthenticationProvider을 살펴보자.

 

 

# AuthenticationProvider

Multiple AuthenticationProviders can be injected into ProviderManager. Each AuthenticationProvider performs a specific type of authentication. For example, DaoAuthenticationProvider supports username/password based authentication while JwtAuthenticationProvider supports authenticating a JWT token.

 

많은 AuthenticationProvider들은 ProviderManager에 주입할 수 있다.

각 AuthenticationProvider 마다 담당하는 인증 방법이 다르다.

예를 들어 DaoAuthenticationProvider는 이름/비밀번호 기반 인증을,

JwtAutenticationProvider는 JWT 토큰 인증을 지원한다.

 

다음으로 AuthenticationProvider의 구현체는 다음과 같다.

구글링에서는 AnonymousAuthenticationProvider가 기본 구현체라고 설명되어있지만, 문서에는 설명되어있지 않아 좀 더 조사가 필요하다.

 

 

 

정리를 해보면

1. 사용자가 요청을 하면

2. 시큐리티 필터에서 인증 정보 바탕으로 인증을 위한 Authentication 객체를 생성하고 AuthenticationManager에게 인증 객체를 넘기며 인증처리를 요구한다.

3. AuthenticationManager는 구현체인 ProviderManger는 가지고 있는 AuthenticationProvider 리스트를 이용하여
인증할 수 있는 provider를 찾고 찾으면 인증 처리를 위임하고 못찾으면 예외를 발생한다.

 

 

이번 포스팅은 문서를 해석하다가 끝난 기분이다.

사실 계속 인증 처리를 위임 -> 위임하는 구조다보니 그런 것 같다.

 

 

댓글