AuthenticationProvider는 사용자 인증 시 어떤 로직을 사용할지를 결정한다.
username&password와 같은 기본적인 인증 외에도 OAUTH2 등의 인증 방식를 필요로 하는 경우가 있는데, 이 때는 서비스의 인증 방식에 맞는 AuthenticationProvider를 구현해야 한다.
AuthenticationManager의 구현체인 ProviderManager의 역할은 가능한 모든 AuthenticationProvider의 구현체를 확인하여 사용자를 인증하는 것이므로, 우리는 실제 인증을 담당하는 AuthenticationProvider만 구현하면 된다.
AuthenticationProvider 인터페이스는 아래와 같다.
AuthenticationProvider

authenticate(), supports()라는 두 메서드로 구성되어있다.
authenticate()는 Authentication 객체를 입력으로 받고 이를 반환한다. 해당 메서드에서 실제 인증 로직이 들어가며 authenticate()를 내가 원하는 인증 방식으로 구현할 수 있다.
support()는 Class<?> authentication을 입력으로 받는데, AuthenticationProvider가 어떤 Authentication 객체 타입을 지원하는지를 명시한다. 해당 Authentication 객체 타입을 지원하면 true를, 그렇지 않으면 false를 반환한다.
아래는 따로 정의한 AuthenticationProvider 코드이다.

로그인은 default로 설정된 값으로 진행되므로, supports() 함수에서 Authentication 객체로 UsernamePasswordAuthenticationToken으로 설정하였다.
authenticate() 메서드에서 실제 인증이 이루어지는데, 인증 과정이 복잡하지 않다면 UserDetailsService 없이 authenticate()에서 직접 인증을 해도 무방하다.
이전에 userDetailsService를 아래와 같이 bean으로 등록을 해놓았으므로 AuthenticationProvider에서 UserDetailsService를 호출하여 UserDetails 정보를 받아왔다.
인증 과정 시 사용자의 나이가 18살 이상일 때 등 추가적인 인증 조건이 필요하다면, authenticationProvider에서 해당 부분을 추가적으로 구현할수도 있다.
