
username과 password를 입력한 뒤, 서버로 요청을 보냄.AuthenticationFilter (예: UsernamePasswordAuthenticationFilter)가 이 요청을 처리할 준비를 함.username과 password를 추출하여, 인증 전 상태의 UsernamePasswordAuthenticationToken 객체를 생성함.principal과 credentials만 포함되며, 아직 인증은 이루어지지 않음.UsernamePasswordAuthenticationToken은 AuthenticationManager의 구현체인 ProviderManager에게 전달됨.AuthenticationProvider들이 등록될 수 있음.ProviderManager는 내부에 등록된 여러 AuthenticationProvider 중, 현재 요청을 처리할 수 있는 Provider를 찾아 인증을 위임함.DaoAuthenticationProvider가 많이 사용되며, 이 단계에서 실제 사용자 정보를 확인함.DaoAuthenticationProvider는 UserDetailsService를 사용해 DB(또는 다른 저장소)에서 사용자 정보를 가져옴.UserDetailsService 인터페이스를 구현한 CustomUserDetailsService 같은 클래스를 만들어 원하는 DB 쿼리 로직을 작성함.UserDetailsService는 DB 조회 결과를 바탕으로 UserDetails 객체(대부분 User 클래스를 상속한 객체)를 반환함.username, password, enabled, authorities (권한 정보) 등이 포함됨.UserDetails와 사용자가 입력한 비밀번호를 비교하여 일치 여부, 계정 잠금 상태 등을 검사함.BCryptPasswordEncoder 등 암호화 기법을 사용해 비교하며, 반드시 동일한 인코더를 사용해야 함.ProviderManager를 통해 최종적으로 인증된 Authentication 객체를 반환함.AuthenticationFilter (예: UsernamePasswordAuthenticationFilter)로 인증 결과가 반환됨.Authentication 객체를 SecurityContext에 저장하고, 성공 핸들러(AuthenticationSuccessHandler)가 동작하거나 지정된 URL로 리다이렉트함.AuthenticationFailureHandler)가 동작하거나 에러 페이지로 리다이렉트함.Authentication 객체는 SecurityContextHolder.getContext().setAuthentication(...)를 통해 SecurityContext에 저장됨.SecurityContextHolder.getContext().getAuthentication()을 통해 현재 사용자 정보를 조회할 수 있음.getAuthorities(): 사용자 권한 목록 반환.getCredentials(): 주로 비밀번호나 인증 토큰 반환.getDetails(): 추가 인증 관련 정보 반환.getPrincipal(): 사용자 정보 반환.isAuthenticated(): 인증 여부 확인.setAuthenticated(boolean): 인증 상태 설정.Authentication 인터페이스를 구현한 클래스로, 폼 기반 인증 시 사용됨.username)와 비밀번호만 포함하며, isAuthenticated()는 false로 설정됨.isAuthenticated()가 true로 변경됨.public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
private final Object principal;
private Object credentials;
// 인증 전: 사용자 ID와 비밀번호만 보유
public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
super(null);
this.principal = principal;
this.credentials = credentials;
setAuthenticated(false);
}
// 인증 후: 권한 정보 포함, 인증된 상태로 생성
public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities) {
super(authorities);
this.principal = principal;
this.credentials = credentials;
super.setAuthenticated(true);
}
}
AuthenticationManager:
authenticate(Authentication) 메서드를 통해 인증을 시도함.public interface AuthenticationManager {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
}
ProviderManager:
public class ProviderManager implements AuthenticationManager {
private List<AuthenticationProvider> providers;
public List<AuthenticationProvider> getProviders() {
return this.providers;
}
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
for (AuthenticationProvider provider : getProviders()) {
if (provider.supports(authentication.getClass())) {
Authentication result = provider.authenticate(authentication);
if (result != null) {
return result;
}
}
}
throw new AuthenticationException("Authentication failed");
}
}
public interface AuthenticationProvider {
Authentication authenticate(Authentication authentication) throws AuthenticationException;
boolean supports(Class<?> authentication);
}
UserDetailsService
public interface UserDetailsService {
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}
UserDetails
public interface UserDetails extends Serializable {
Collection<? extends GrantedAuthority> getAuthorities();
String getPassword();
String getUsername();
boolean isAccountNonExpired();
boolean isAccountNonLocked();
boolean isCredentialsNonExpired();
boolean isEnabled();
}
SecurityContext:
SecurityContextHolder:
SecurityContextHolder.getContext().setAuthentication(authentication);
SecurityContextHolder.getContext().getAuthentication();
UserDetailsService에서 로드된 권한 정보를 기반으로 접근 제어나 권한 검증을 수행함.