KKanging

[SpringSecurity] 인증 과정 뜯어보기 본문

백엔드/SpringSecurity

[SpringSecurity] 인증 과정 뜯어보기

천방지축 개발자 2024. 5. 26. 15:23

UsernamePasswordAuthenticationFilter란

우리가 로그인을 시도할 때 Security에서 기본적으로 동작하는 Filter이다.

Security에서 디폴트로 제공하고 만약 SecurityFilterChain을 커스텀한다면 제공해주지 않는다.

즉, 우리가 주로 커스텀 해야하는 Filter라는 뜻이다.

AuthenticationFilter 구조

AuthenticationFilter의 기본 호출 구조이다.

호출 순서는 다음과 같다

  1. AuthenticationFilter호출
  2. UsernamePasswordAuthenticationToken (비인증) 생성
  3. AuthenticationManager.authenticate(token) 호출
    • 구현체인 ProviderManager 호출
    • ProviderManager 는 AuthenticationProvider 리스트를 가지고 있음
  4. AuthenticationProvider의 supports 메서드로 호환되는 provider 를 찾음 호환 된다면 authenticate() 호출
  5. 해당 AuthenticationProvider의 UserDetailsService 로 loadUserByUsername 호출하여 db에서 조회한다.
  6. 클라이언트가 입력한 정보에 맞는 User를 db에서 조회하여 UserDetails 반환
  7. UserDetails 반환
  8. Authentication반환
  9. Authentication반환
  10. 성공한다면 context 에 저장
    • 성공하면 successfulAuthentication() 호출
    • 실패하면 unsuccessfulAuthentication() 호출

AuthenticationFilter 호출 뜯어보기

1. AuthenticationFilter 호출

만약 AuthenticationFilter를 커스텀한다면 security에 기본적으로 제공하는 UsernamePasswordAuthenticationFitler 이나 UsernamePasswordAuthenticationFitler의 inteface인 AbstractAuthenticationProcessingFilter 를 상속 받는다면

AuthenticationFilter의 핵심 로직은 doFilter 가 아닌 attemptAuthentication이다. 이는 AbstractAuthenticationProcessingFilter 를 보면 알 수 있다.

  • AbstractAuthenticationProcessingFilter 코드

위에를 보면 doFilter 안에 attemptAuthentication 을 호출하여 인증 로직을 수행하는 것을 볼 수 있다.

2. UsernamePasswordAuthenticationToken (비인증) 생성

UsernamePasswordAuthenticationToken authRequest = 
				UsernamePasswordAuthenticationToken.unauthenticated(username,password);

비인증 Token을 생성한다

UsernamePasswordAuthenticationToken 은 Authentication 을 상속 받은 클래스이고

principal 과 credentials 를 그리고 authenticaated 를 false로 생성한다

  • 기본 default가 authenticated가 false이다.

3. AuthenticationManager.authenticate(token) 호출

등록된 AuthenticationProvider 를 list로 가지고 있다

4. AuthenticationProvider의 supports 메서드로 호환되는 provider 를 찾음 호환 된다면 authenticate() 호출

지원하는 provder를 supports로 찾고 있으면 authenticate를 호출한다.

5. 해당 AuthenticationProvider의 UserDetailsService 로 loadUserByUsername 호출하여 db에서 조회한다.

마지막 : contextHolder에 저장

  • UsernamePasswordAuthenticationFilter 예시

모든 과정이 끝나면 attemmptAuthentication 은 Authentication 객체를 반환한다.

성공적으로 저장 할 시에는 Authentication을 context에 저장한다.

성공적으로 수행된다면 successfulAuthentication 을 호출한다.

다음 filter를 호출하는 doFilter는 this.continueChainBeforeSuccessfulAuthentication이 true여야 하는데 기본은 false로 되어있다.