[스프링 시큐리티] 인증 절차


1

Authentication 객체가 Security Context에 들어가면 세션이 저장됨

  1. Http Request
    • 로그인 요청 (username, password)
  2. UsernamePasswordAuthenticationToken
    • 사용자의 username과 password로 토큰을 생성
    • 생성된 토큰을 AuthenticationManager 구현체인 ProviderManager에 전달
    • UsernamePasswordAuthenticationToken은 Authentication 인터페이스의 구현체
    • Authentication 구현체를 AuthenticationManager에 전달해야 인증 과정 수행 가능
      • 즉, 커스텀 인증 방식을 구현하고 싶다?
        • UsernamePasswordAuthenticationFilter와 유사한 필터를 만들어서 Autentication 구현체를 AuthenticationManager에게 전달해주면 됨
  3. 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;
        
  4. AuthenticationProvider
    • 실질적인 인증을 담당하는 인터페이스
    • UserDetailService 인터페이스를 구현한 구현체로부터 DB의 유저 정보(username, password)를 가져옴
    • UserDetailService로 가져온 username과 password를 Authentication(token) 객체의 username, password와 일치하는지 비교함
  5. 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;
        }
       }
      





© 2020.02. by blupine