문제 상황
RestAuthenticationProvider는 Spring Security에서 인증(Authentication)을 처리하는 컴포넌트 중 하나로, REST API 환경에 적합하게 설계된 AuthenticationProvider의 구현체다. 이 클래스는 클라이언트로부터 받은 인증 정보를 검증하고, 성공적으로 인증이 완료되면 인증된 사용자 정보를 반환한다. 주로 사용자 이름과 비밀번호를 통해 인증을 처리하거나, 토큰 기반 인증을 처리할 수 있도록 확장할 수 있다.
RestAuthenticationProvider
1. AuthenticationProvider의 역할
AuthenticationProvider는 Spring Security에서 사용자 인증을 처리하는 핵심 인터페이스다. authenticate 메서드를 통해 인증 정보를 받아, 이를 검증하고, 검증에 성공하면 인증된 사용자 정보를 포함한 Authentication 객체를 반환한다. 여러 AuthenticationProvider가 등록될 수 있으며, 각각의 Provider는 특정한 인증 방식에 대해 처리할 수 있다.
2. RestAuthenticationProvider의 구조
RestAuthenticationProvider는 RESTful API에서 사용자 인증을 처리하는 역할을 한다. 주로 AJAX 요청이나 비동기 방식의 인증을 처리할 때 사용된다. 이 클래스는 일반적으로 사용자 이름과 비밀번호를 기반으로 사용자 정보를 조회하고, 비밀번호 일치 여부를 검증하는 방식으로 동작한다.
-
코드 설명
@Primary
@Component("restAuthenticationProvider")
// 이 클래스가 Spring Security의 AuthenticationProvider 빈으로 등록됨을 나타냄.
// @Primary: 동일한 타입의 여러 AuthenticationProvider 빈이 있을 때, 이 빈이 기본적으로 선택됨을 명시.
// @Component("restAuthenticationProvider"): 이 클래스가 빈으로 등록되며, 빈 이름을 "restAuthenticationProvider"로 설정.
@RequiredArgsConstructor
// Lombok의 어노테이션으로, final 필드에 대한 생성자를 자동으로 생성해줌.
// UserDetailsService와 PasswordEncoder가 주입되는 생성자가 생성됨.
public class RestAuthenticationProvider implements AuthenticationProvider {
private final UserDetailsService userDetailsService;
// 사용자 정보를 조회하기 위한 서비스. Spring Security에서 사용자의 이름을 기반으로 UserDetails 객체를 가져옴.
private final PasswordEncoder passwordEncoder;
// 비밀번호를 암호화 및 비교하는 도구. Spring Security에서 제공하는 PasswordEncoder를 통해 비밀번호를 안전하게 저장 및 검증.
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
String loginId = authentication.getName();
// 클라이언트가 입력한 로그인 ID(사용자 이름)를 가져옴.
String password = (String) authentication.getCredentials();
// 클라이언트가 입력한 비밀번호를 가져옴.
AccountContext accountContext = (AccountContext) userDetailsService.loadUserByUsername(loginId);
// UserDetailsService를 사용하여, 입력된 로그인 ID를 기반으로 데이터베이스에서 사용자 정보를 조회함.
// 조회된 사용자 정보는 AccountContext 객체에 담김 (AccountContext는 UserDetails를 구현한 커스텀 클래스).
if (!passwordEncoder.matches(password, accountContext.getPassword())) {
// 클라이언트가 입력한 비밀번호와 데이터베이스에 저장된 암호화된 비밀번호를 비교.
// 비밀번호가 일치하지 않으면 인증 실패로 처리하고, BadCredentialsException을 던짐.
throw new BadCredentialsException("Invalid password");
// 인증 실패 시 예외를 던져 Spring Security가 이 예외를 처리하게 됨.
}
return new RestAuthenticationToken(accountContext.getAccountDto(), null, accountContext.getAuthorities());
// 비밀번호가 일치하면 인증 성공으로 처리되고, RestAuthenticationToken을 반환.
// 이 토큰에는 인증된 사용자의 정보(AccountDto)와 권한 목록(authorities)이 포함됨.
}
@Override
public boolean supports(Class<?> authentication) {
return authentication.isAssignableFrom(RestAuthenticationToken.class);
// 이 AuthenticationProvider가 처리할 수 있는 Authentication 토큰 타입을 지정함.
// 여기서는 RestAuthenticationToken을 처리하도록 설정.
}
}