[스프링 시큐리티] 인증 절차
Authentication 객체가 Security Context에 들어가면 세션이 저장됨
- Http Request
- 로그인 요청 (username, password)
- UsernamePasswordAuthenticationToken
- 사용자의 username과 password로 토큰을 생성
- 생성된 토큰을 AuthenticationManager 구현체인 ProviderManager에 전달
- UsernamePasswordAuthenticationToken은 Authentication 인터페이스의 구현체
- Authentication 구현체를 AuthenticationManager에 전달해야 인증 과정 수행 가능
- 즉, 커스텀 인증 방식을 구현하고 싶다?
- UsernamePasswordAuthenticationFilter와 유사한 필터를 만들어서 Autentication 구현체를 AuthenticationManager에게 전달해주면 됨
- 즉, 커스텀 인증 방식을 구현하고 싶다?
- AuthenticationManager«interface»
- Authentication 구현체(위에선 Token)을 전달받아서 인증을 진행
- 인증되었으면 인증된 Authentication 객체를 돌려줌
isAuthenticated(boolean)
이 True로 설정됨- ProviderManager?
- AuthenticationManager의 구현체 (스프링 시큐리티에서 인증을 담당하는 클래스)
- 그러나 직접 인증을 수행하는 것이 아닌 멤버 변수로 가지는 AuthenticationProvider 인터페이스 구현체에게 인증은 위임
- AuthenticationProvider의 authentication 메소드가 인증이 완료된 Authentication 객체를 반환하고 AuthenticationManager도 그걸 반환함
/* ProviderManager.class */ @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { /* 생략 */ // 자신이 가지고 있는 ProviderManager들을 순회하면서 인증을 위임 for (AuthenticationProvider provider : getProviders()) { /* 생략 */ try { result = provider.authenticate(authentication); // Provider의 Authentication 호출 if (result != null) { /* 생략 */ return result;
- AuthenticationProvider
- 실질적인 인증을 담당하는 인터페이스
- UserDetailService 인터페이스를 구현한 구현체로부터 DB의 유저 정보(username, password)를 가져옴
- UserDetailService로 가져온 username과 password를 Authentication(token) 객체의 username, password와 일치하는지 비교함
- UserDetailService
loadUserByUsername
메소드에서 User 객체를 반환- 이후 Provider에서 해당 객체를 비교, 인증 성공 시 Authentication 구현체(token)에 isAuthenticated를 true로 설정
- 이후 Security Context에 해당 객체가 저장되면서 세션이 저장됨
public class AccountService implements UserDetailsService { @Override public UserDetails loadUserByUsername(String eamilOrNickname) throws UsernameNotFoundException { Account account = accountRepository.findByEmail(eamilOrNickname); if(account == null){ account = accountRepository.findByNickname(eamilOrNickname); } if(account == null){ return null; } return new UserAccount(account); }
public class UserAccount extends User { private Account account; public UserAccount(Account account) { super(account.getNickname(), account.getPassword(), List.of(new SimpleGrantedAuthority("ROLE_USER"))); this.account = account; } }