Spring-Security4에서 Google API에 대한 로그인, 회원가입 처리를 완료하였다
하지만 뒤에 추가적으로 FaceBook, Naver, Kakao API를 추가하였고, 이에 대한 로그인, 회원가입 처리를 하게되었다
attributes
# 구글
attributes : {sub={고유 id}, name={이름}, given_name={이름}, family_name={성}, picture={프로필사진}, email={이메일}, email_verified=true, locale=ko}
# 페이스북
attributes : {id={고유 id}, name={이름}, email={이메일}}
# 네이버
attributes : {resultcode=00, message=success, response={id={고유 ID}, email={이메일}, name={이름}}}
#카카오
attributes : {id={고유 id}, connected_at={접근시간}, properties={nickname=.}, kakao_account={profile_nickname_needs_agreement=false, profile_image_needs_agreement=true, profile={nickname=.}, has_email=true, email_needs_agreement=false, is_email_valid=true, is_email_verified=true, email={이메일}}}
하지만 위처럼 attribute를 받아온 결과, attributes값들이 서로 상이함을 알 수 있다
이를 위해 DefaultOAuth2UserService를 상속받은 클래스에서 loadUser가 실행될때 각 서비스별로 별도의 처리가 필요하다
이를 위해 하나의
@Override
public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
OAuth2User oAuth2User = super.loadUser(userRequest);
OAuth2UserInfo oAuth2UserInfo = null;
switch (userRequest.getClientRegistration().getRegistrationId()) {
case "google":
oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
break;
case "facebook":
oAuth2UserInfo = new FacebookUserInfo(oAuth2User.getAttributes());
break;
case "naver":
oAuth2UserInfo = new NaverUserInfo((Map)oAuth2User.getAttributes().get("response"));
break;
case "kakao":
oAuth2UserInfo = new KakaoUserInfo(oAuth2User.getAttributes());
break;
default:
log.info("지원하지 않는 OAuth 입니다");
break;
}
Optional<User> userOptional = userRepository.findByProviderAndProviderId(oAuth2UserInfo.getProvider(),
oAuth2UserInfo.getProviderId());
User user;
if (userOptional.isPresent()) {
user = userOptional.get();
user.setEmail(oAuth2UserInfo.getEmail());
userRepository.save(user);
} else {
user = User.builder()
.username(oAuth2UserInfo.getProvider() + "_" + oAuth2UserInfo.getProviderId())
.email(oAuth2UserInfo.getEmail())
.password(passwordEncoder.encode("패스워드"))
.role("ROLE_USER")
.provider(oAuth2UserInfo.getProvider())
.providerId(oAuth2UserInfo.getProviderId())
.build();
userRepository.save(user);
}
return new PrincipalDetails(user, oAuth2User.getAttributes());
}
이를 위해 위처럼 oAuth2UserInfo 인터페이스를 생성하여, 서비스별로 별도의 값을 받는 처리를 해주었다
public interface OAuth2UserInfo {
String getProviderId();
String getProvider();
String getEmail();
String getName();
}
import java.util.Map;
public class FacebookUserInfo implements OAuth2UserInfo {
private Map<String, Object> attributes;
public FacebookUserInfo(Map<String, Object> attributes){
this.attributes = attributes;
}
@Override
public String getProviderId() {
return (String)attributes.get("id");
}
@Override
public String getProvider() {
return "facebook";
}
@Override
public String getEmail() {
return (String)attributes.get("email");
}
@Override
public String getName() {
return (String)attributes.get("name");
}
}
import java.util.Map;
public class NaverUserInfo implements OAuth2UserInfo{
private Map<String, Object> attributes;
public NaverUserInfo(Map<String, Object> attributes){
this.attributes = attributes;
}
@Override
public String getProviderId() {
return (String)attributes.get("id");
}
@Override
public String getProvider() {
return "naver";
}
@Override
public String getEmail() {
return (String)attributes.get("email");
}
@Override
public String getName() {
return (String)attributes.get("name");
}
}
import java.util.Map;
public class GoogleUserInfo implements OAuth2UserInfo{
private Map<String, Object> attributes;
public GoogleUserInfo(Map<String, Object> attributes){
this.attributes = attributes;
}
@Override
public String getProviderId() {
return (String)attributes.get("sub");
}
@Override
public String getProvider() {
return "google";
}
@Override
public String getEmail() {
return (String)attributes.get("email");
}
@Override
public String getName() {
return (String)attributes.get("name");
}
}
import java.util.Map;
public class KakaoUserInfo implements OAuth2UserInfo{
private Map<String, Object> attributes;
private Map<String, Object> accountAttributes;
private Map<String, Object> propertiesAttributes;
public KakaoUserInfo(Map<String, Object> attributes){
this.attributes = attributes;
this.accountAttributes = (Map)attributes.get("kakao_account");
this.propertiesAttributes = (Map)attributes.get("properties");
}
@Override
public String getProviderId() {
return attributes.get("id").toString();
}
@Override
public String getProvider() {
return "kakao";
}
@Override
public String getEmail() {
return (String)accountAttributes.get("email");
}
@Override
public String getName() {
return (String)propertiesAttributes.get("nickname");
}
}
이 외 oAuth2User.getAttributes() 값을 확인하여 필요에 따라 메소드를 수정하자