본문 바로가기

Server/Spring

[Spring Security] 로그인 예외 처리를 해보겠습니다. (feat. @ControllerAdvice)

Spring Security 에서 인증(로그인)시에 예외가 발생할 수 있는데 이를 처리하는 과정을 정리해보고자 합니다. 

 

📍 인증 과정에서 예외가 발생하는 이유

Spring Security 에서 로그인 요청이 들어오면 AuthenticationManager 가 인증을 시도합니다. 이 과정에서 적절한 AuthenticationProvider 를 선택하여 인증을 수행하는데, 아이디나 비밀번호가 잘못된 경우, 계정이 잠긴 경우 등 다양한 이유로 인증이 실패할 수 있습니다.

 

인증이 실패하면 AuthenticationException 이 발생합니다. SpringSecurity 는 이를 상속하는 다양한 예외 클래스를 제공하여, 실패 원인에 따라 다른 예외가 발생하도록 합니다. 



📍인증 과정에서 예외가 발생하는 흐름

로그인 과정에서 예외가 발생하는 경로를 따라가보았습니다. 

 

1️⃣ 로그인 요청을 받으면 AuthenticationManager 에게 인증을 위임하도록 하였습니다.

authenticationManager.authenticate(
    new UsernamePasswordAuthenticationToken(username, password)
);

AuthenticationManager 의 구현체는 ProviderManager 입니다. 

 

2️⃣ AuthenticationManger 의 구현체인 ProviderManagerAuthenticationProvider 를 선택하여 인증을 진행합니다.  

  • ProviderManager 는 여러 개의 AuthenticationProvider 중 가장 적절한 Provider 를 선택하며, 기본적으로 DaoAuthenticationProvider 가 선택됩니다.
public class ProviderManager implements AuthenticationManager {
    private List<AuthenticationProvider> providers;
    
    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
        for (AuthenticationProvider provider : providers) {
            if (provider.supports(authentication.getClass())) {
                return provider.authenticate(authentication);
            }
        }
        throw new AuthenticationException("인증 실패");
    }
}

 

3️⃣ DaoAuthenticationProvider 가 사용자 정보를 조회하고 인증을 검증합니다.

 

  • UserDetailsService를 이용하여 사용자 정보 조회
  • 비밀번호 검증 후 불일치하면 BadCredentialsException 발생
  • 사용자가 없으면 UsernameNotFoundException 발생

 

public class DaoAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
    @Override
    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
        if (!passwordEncoder.matches(authentication.getCredentials().toString(), userDetails.getPassword())) {
            throw new BadCredentialsException("아이디 또는 비밀번호가 일치하지 않습니다.");
        }
    }
}

 

 

DaoAuthenticationProviderAbstractUserDetailsAuthenticationProvider 를 상속받은 클래스입니다. 

 

📍@ControllerAdvice 를 활용한 예외 처리

인증 과정에서 발생하는 예외를 한 곳에서 관리하고, 사용자가 이해할 수 있는 커스텀 응답(JSON) 형태로 변환하기 위해 @ControllerAdvice 를 활용하였습니다. 

 

✅ 최종 정리

  1. Spring Security의 인증 과정
    • AuthenticationManager → ProviderManager → DaoAuthenticationProvider
    • 사용자가 로그인 요청을 하면, DaoAuthenticationProvider에서 비밀번호 검증
    • 검증 실패 시 AuthenticationException 발생
  2. @ControllerAdvice 를 활용한 예외 처리
    • @ExceptionHandler 를 이용해 인증 예외를 잡아서 커스텀 JSON 응답 반환
    • 사용자가 쉽게 이해할 수 있도록 적절한 에러 메시지 제공

 

 

참고

https://beaniejoy.tistory.com/93