외부에서 가져온 모든 그림, 사진은 링크로 출처를 표기해 뒀습니다.
해당 그림, 사진을 누르며 출처로 이동합니다.
UsernamePasswordAuthenticationFilter
클래스가 해당 요청을 전달 받는다.UsernamePasswordAuthenticationFilter
클래스는 사용자 이름과 비밀번호를 추출한다. UsernamePasswordAuthenticationFilter
클래스에 있는 attemptAuthentication()
메서드를 통해 인증 시도를 시작한다.@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
// 생략
}
UsernamePasswordAuthenticationToken
객체를 생성한다.UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, password);
AuthenticationManager
인터페이스를 통해 인증 처리를 진행한다. authenticate()
메서드를 호출하여 인증 처리를 시작한다.public interface AuthenticationManager {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
AuthenticationProvider
처리AuthenticationProvider
에서 UserDetailsService
를 사용하여 데이터베이스에서 사용자 정보를 조회한다.UserDetails
는 데이터베이스 등의 저장소에 저장된 사용자의 Username과 사용자의 자격을 증명해주는 크리덴셜(Credential)인 Password, 그리고 사용자의 권한 정보를 포함하고 있는 컴포넌트다.UserDetails
를 제공하는 컴포넌트가 바로 UserDetailsService
다.loadUserByUsername()
메서드를 호출하여 사용자 정보를 가져온다.public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
AuthenticationProvider
는 인증된 사용자의 권한 정보를 포함한 새로운 UsernamePasswordAuthenticationToken
객체를 생성한다.UsernamePasswordAuthenticationToken authenticatedToken = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
SecurityContextHolder.getContext().setAuthentication(authenticatedToken);
AuthenticationManager
는 인증 처리를 총괄하는 매니저 역할을 하는 인터페이스이고,AuthenticationManager
를 구현한 구현 클래스가ProviderManager
이다.
UsernamePasswordAuthenticationFilter
가 생성하는 Authentication은 인증을 위해 필요한 사용자의 로그인 정보를 가지고 있다.AuthenticationProvider
가 생성한 Authentication은 인증에 성공한 사용자의 정보(Principal, Credential, GrantedAuthorities)를 가지고 있다.
- 인증된 Authentication을 전달 받은
UsernamePasswordAuthenticationFilter
는SecurityContextHolder
를 이용해SecurityContext
에 인증된Authentication
을 저장한다.SecurityContext
는 이 후에HttpSession
에 저장되어 사용자의 인증 상태를 유지한다.
UsernamePasswordAuthenticationFilter
서블릿 필터(클래스)
AbstractAuthenticationProcessingFilter
를 상속받아 구현되어 있다.UsernamePasswordAuthenticationToken
객체를 생성한다.attemptAuthentication()
메서드를 호출한다.Authentication
객체를 성공적으로 인증된 사용자로 설정한다.AbstractAuthenticationProcessingFilter
서블릿 필터(클래스)
이 클래스를 상속받아 인증 처리 과정을 구현할 수 있다. 예를 들어 UsernamePasswordAuthenticationFilter
는 이 클래스를 상속받아 사용자 이름과 비밀번호를 기반으로 한 인증 처리를 구현한다.
HTTP 기반의 인증 요청을 처리하지만 실질적인 인증 시도는 하위 클래스에 맡기고, 인증에 성공하면 인증된 사용자의 정보를 SecurityContext에 저장하는 역할을 한다.
attemptAuthentication()
메서드는 인증을 시도하는 주요 메서드로, 구체적인 인증 로직은 이 메서드를 구현하여 작성한다.
인증이 성공적으로 이루어진 경우, successfulAuthentication()
메서드가 호출되어 인증 성공에 따른 후속 처리를 수행한다.
인증 과정에서 실패할 경우, unsuccessfulAuthentication()
메서드를 호출하여 인증 실패에 따른 후속 처리를 수행한다.
AbstractAuthenticationProcessingFilter
는 서블릿 필터의 인터페이스를 구현하며, doFilter() 메서드를 오버라이딩하여 인증 처리를 수행하는 로직을 제공한다.
사용자 정의 인증 처리를 구현하기 위해 이 클래스를 상속받아 필요한 메서드를 오버라이딩하고 확장할 수 있다.
UsernamePasswordAuthenticationToken
클래스
사용자 이름과 비밀번호를 기반으로 한 인증 토큰 객체로 사용한다.
Authentication
인터페이스를 구현한다.
주요 정보는 사용자 이름(principal), 비밀번호(credentials) 및 인증된 사용자의 권한(authorities)을 포함한다.
인증 전과 인증 후의 토큰 상태를 나타낼 수 있다. 인증 전에는 사용자 이름과 비밀번호만 포함하며, 인증 후에는 권한 정보가 추가된다.
인증 과정에서 UsernamePasswordAuthenticationToken
객체를 사용하여 사용자의 인증 정보를 전달하고, 인증 후에는 인증된 사용자의 권한 정보를 포함한 토큰 객체를 반환한다.
인증 과정에서 사용되는 주요 인증 토큰으로, AuthenticationProvider
와 UserDetails
객체와 함께 사용되어 인증 처리를 수행한다.
인증 과정에서 발생하는 인증 요청 및 인증 결과의 표현을 담당하며, 인증 정보를 저장하고 전달하는 역할을 수행한다.
Authentication
인터페이스
Spring Security에서 인증 정보를 표현하는 핵심 인터페이스이다.
인증 정보는 주로 다음의 구성 요소를 포함한다.
인증 과정 중에 Authentication
객체는 인증 요청의 표현 및 인증 결과의 저장을 담당한다.
인증 처리기(AuthenticationManager
)에서 인증을 진행한 후, 인증된 사용자의 정보와 권한을 포함한 Authentication
객체가 반환된다.
인증된 사용자의 인증 정보는 SecurityContextHolder
에 저장되어 애플리케이션 전반에 걸쳐 접근 가능하다.
다양한 인증 방식에 따라 다양한 구현체를 가질 수 있다. 예를 들어, UsernamePasswordAuthenticationToken
은 사용자 이름과 비밀번호 기반의 인증을 위한 구현체다.
AuthenticationManager
인터페이스
인증 처리를 총괄하는 매니저 역할을 하는 인터페이스
authenticate()
메서드 하나만 정의되어 있다.
authenticate()
= 전달된 인증 정보를 기반으로 인증을 수행하고, 인증에 성공한 경우 인증된 사용자 정보와 권한을 포함한 Authentication
객체를 반환하는 메서드인증을 위한 Filter는 AuthenticationManager
를 통해 느슨한 결합을 유지하고 있으며, 인증을 위한 실질적인 관리는 AuthenticationManager
를 구현하는 구현 클래스를 통해 이루어진다.
ProviderManager
ProviderManager
클래스
AuthenticationManager
인터페이스를 구현하는 클래스다.
AuthenticationProvider
를 관리하고, AuthenticationProvider
에게 인증 처리를 위임하는 역할을 한다.
List<AuthenticationProvider>
객체를 DI 받는다.
authenticate()
메서드에서 DI 받은 List와 반복문을 이용해 적절한 AuthenticationProvider를 찾는다.
public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
...
...
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
...
...
for (AuthenticationProvider provider : getProviders()) {
if (!provider.supports(toTest)) {
continue;
}
if (logger.isTraceEnabled()) {
logger.trace(LogMessage.format("Authenticating request with %s (%d/%d)",
provider.getClass().getSimpleName(), ++currentPosition, size));
}
try { // 찾으면 해당 AuthenticationProvider에게 인증 처리를 위임
result = provider.authenticate(authentication);
if (result != null) {
copyDetails(authentication, result);
break;
}
}
catch (AccountStatusException | InternalAuthenticationServiceException ex) {
prepareException(ex, authentication);
// SEC-546: Avoid polling additional providers if auth failure is due to
// invalid account status
throw ex;
}
catch (AuthenticationException ex) {
lastException = ex;
}
}
...
...
}
}
authenticate()
메서드에서 인증이 정상적으로 처리되면 인증에 사용된 Credentials를 제거한다.AuthenticationProvider
인터페이스
실질적인 인증 수행을 담당하는 컴포넌트다.
주요 메서드로는 authenticate()
와 supports()
가 있다. authenticate()
메서드는 인증 요청을 처리하고, supports()
메서드는 해당 AuthenticationProvider
가 특정 인증 유형을 지원하는지 확인한다.
위에서 자세히 설명한 authenticate()
메서드는 전달된 인증 요청이 유효한지 검사하고, 인증된 사용자 정보와 권한을 포함한 Authentication
객체를 반환한다. 인증에 실패한 경우, AuthenticationException
을 발생시킨다.
supports()
메서드는 인증 요청 객체의 유형이 해당 AuthenticationProvider
에서 처리할 수 있는 유형인지 확인한다. 이를 통해 ProviderManager
가 적절한 AuthenticationProvider
를 선택하여 인증 처리를 진행한다.
일반적으로 UserDetails
를 로드(load)하는 UserDetailsService
와 함께 사용된다. UserDetailsService
는 사용자 정보를 로드하고, AuthenticationProvider
는 로드된 사용자 정보와 클라이언트로부터 전달받은 인증 정보를 비교하여 인증을 수행한다.
Spring Security에서는 다양한 AuthenticationProvider
구현체를 제공한다. 예를 들어, DaoAuthenticationProvider
는 사용자 이름과 비밀번호를 기반으로 하는 인증을 처리하며, OAuth2 인증 방식을 처리하는 OAuth2AuthenticationProvider도 있다.
UserDetails
인터페이스
데이터베이스 등의 저장소에 저장된 사용자의 Username과 사용자의 자격을 증명해주는 크리덴셜(Credential)인 Password 그리고 사용자의 권한 정보를 포함하는 컴포넌트다.
위에서 언급한 AuthenticationProvider
가 UserDetails
를 이용해 자격 증명을 수행한다.
사용자 이름, 비밀번호, 권한, 계정 잠금 여부 등 인증에 필요한 사용자 정보를 포함한다.
사용자 정보를 저장하고 관리하는 데 사용된다.
UserDetailsService
인터페이스
UserDetails
객체를 로드하는 인터페이스다.
loadUserByUsername(String username)
메서드를 구현해야 한다.
SecurityContext
인터페이스와 SecurityContextHolder
클래스의 관계도는 아래그림과 같다.
Spring Security 입장에서는 SecurityContextHolder에 의해 SecurityContext에 값이 채워져 있다면 인증된 사용자로 간주한다.
SecurityContext
는 인증된 사용자의 정보와 관련된 보안 정보를 저장하는 객체이다.
SecurityContextHolder
는 SecurityContext
객체를 저장하고 관리하는 유틸리티 클래스이다.
SecurityContextHolder
를 사용하면 현재 인증된 사용자의 정보를 가져오거나 수정할 수 있다.
SecurityContextHolder
는 기본적으로 다음 세 가지 전략을 사용하여 SecurityContext를 관리한다.
Spring Security에서 인증이 완료되면, 인증된 사용자의 정보를 담고 있는 Authentication
객체를 SecurityContext
에 저장한다. 이후에는 SecurityContextHolder
의 getContext()
메서드를 통해 현재 인증된 사용자의 정보를 가져올 수 있다.
SecurityContextHolder.clearContext() 메서드를 사용하여 현재 스레드의 SecurityContext를 초기화할 수 있다. 이 메서드는 보통 로그아웃 처리 시에 사용된다.
UsernamePasswordAuthenticationFilter
는 클라이언트로부터 전달받은 Username과 Password를 Spring Security가 인증 프로세스에서 이용할 수 있도록 UsernamePasswordAuthenticationToken
을 생성한다.
AbstractAuthenticationProcessingFilter
는 HTTP 기반의 인증 요청을 처리하지만 실질적인 인증 시도는 하위 클래스에 맡기고, 인증에 성공하면 인증된 사용자의 정보를 SecurityContext
에 저장하는 역할을 한다.
Authentication
은 Spring Security에서의 인증 자체를 표현하는 인터페이스이다.
AuthenticationManager
는 이름 그대로 인증 처리를 총괄하는 매니저 역할을 하는 인터페이스이며, 인증을 위한 실질적인 관리는 AuthenticationManager
를 구현하는 구현 클래스(ProviderManager
)를 통해 이루어진다.
ProviderManager
는AuthenticationProvider
를 관리하고, AuthenticationProvider
에게 인증 처리를 위임하는 역할을 한다.
AuthenticationProvider
는 AuthenticationManager
로부터 인증 처리를 위임받아 실질적인 인증 수행을 담당하는 컴포넌트이다.
UserDetails
는 데이터베이스 등의 저장소에 저장된 사용자의 Username과 사용자의 자격을 증명해주는 크리덴셜(Credential)인 Password 그리고 사용자의 권한 정보를 포함하는 컴포넌트이며, AuthenticationProvider
는 UserDetails
를 이용해 자격 증명을 수행한다.
UserDetailsService
는 UserDetails
를 로드(load)하는 핵심 인터페이스이다.
SecurityContext
는 인증된 Authentication
객체를 저장하는 컴포넌트이고, SecurityContextHolder
는 SecurityContext
를 관리하는 역할을 담당한다.
DelegatingFilterProxy는 Spring Security의 필터 체인을 다른 서블릿 컨테이너에 적용하기 위해 사용된다. 이 필터는 web.xml 파일에서 설정된 필터를 찾아 그 필터를 실행하는 역할을 한다. 이를 통해 Spring Security의 필터 체인을 다른 서블릿 컨테이너에서도 적용할 수 있다. 또한, DelegatingFilterProxy는 서블릿 컨테이너에서 필터 체인을 직접 관리하기 때문에 필터의 라이프사이클 관리를 Spring에 위임할 수 있다.