* UserDetails, UserDetailsService를 개발자가 직접 구현해야 하는 이유
: 개발환경에 따라 구현 방법이 천차만별이기 때문에
사용자는 아이디/비밀번호를 입력하고 로그인 요청을 서버로 보낸다.
AuthenticaitonFilter는 로그인 요청을 받는다.
AuthenticationFilter의 구현체인 UsernamePasswordAuthenticationFilter는
인증 전 Authentication 구현객체(UsernamePasswordAuthenticationToken)를 생성한다.
인증 전 Authentication 객체에는 아래의 값이 저장된다.
principal = 사용자 아이디, credential = 비밀번호, authenticated = false, authorities = null
AuthenticationFilter는 인증 전 Authentication 객체를 AuthenticationManager에게 전달해서 인증을 요청한다.
AuthenticationManager는 구현체인 ProviderManager에 등록된 AuthenticationProvider에게 인증 전 Authentication 객체를 전달해서 인증처리를 위임한다.
AuthenticationProvider는 UserDetailsService의 loadUserByUsername(String username) 메서드를 실행해서 사용자 정보를 조회한다.
조회된 사용자정보는 UserDetails 객체를 생성해서 저장한다.
AuthenticationProvider는 조회된 사용자정보가 담긴 UserDetails객체를 전달받고, 사용자 인증을 수행한다.
AuthenticationProvider는 인증이 완료되면 인증 후 Authentication 객체를 생성해서 AuthenticationManager에게 반환한다.
principal = UserDetails객체, credential = 비밀번호, authenticated = true, authorities = List<GrantedAuthority> 객체
AuthenticationManager는 인증 후 Authentication객체를 반환한다.