프로필

프로필 사진
Popomon
Frontend Developer
(2020/12 ~)

    카테고리

    포스트

    Spring Security - Social Login Model (Google / Github / Facebook)

    2020. 2. 20. 06:12

    꿈가게: To Do List - iOS

    꿈가게: To Do List - Android

    유저 정보에는 ID / Name / Email / ImageUrl 총 4가지의 정보를 다루겠습니다.

    하지만 소셜 로그인 API 종류에 따라 각각 다른 이름으로 값을 넘겨줍니다.

     

    따라서 각각 다른 방법으로 값을 추출해야 합니다. OAuth2UserInfo 추상클래스를 상속받아서 각각의 소셜 로그인에 해당하는 UserInfo 클래스를 작성해 보겠습니다.

     

     

    사이트 종류에 따른 컬럼명

    컬럼명 Google Github Facebook
    id sub id (숫자) id
    name name name name
    email email email email
    imageUrl picture avatar_url picture.data.url

     

     

    OAuth2UserInfo - 추상클래스

    import java.util.Map;
    
    public abstract class OAuth2UserInfo {
        protected Map<String, Object> attributes;
    
        public OAuth2UserInfo(Map<String, Object> attributes) {
            this.attributes = attributes;
        }
    
        public Map<String, Object> getAttributes() {
            return attributes;
        }
    
        public abstract String getId();
    
        public abstract String getName();
    
        public abstract String getEmail();
    
        public abstract String getImageUrl();
    }

     

     

    GoogleOAuth2UserInfo - 구현 클래스

    import com.example.rest.security.oauth2.userinfo.OAuth2UserInfo;
    
    import java.util.Map;
    
    public class GoogleOAuth2UserInfo extends OAuth2UserInfo {
        public GoogleOAuth2UserInfo(Map<String, Object> attributes) {
            super(attributes);
        }
    
        @Override
        public String getId() {
            return (String) attributes.get("sub");
        }
    
        @Override
        public String getName() {
            return (String) attributes.get("name");
        }
    
        @Override
        public String getEmail() {
            return (String) attributes.get("email");
        }
    
        @Override
        public String getImageUrl() {
            return (String) attributes.get("picture");
        }
    }
    

     

     

     GithubOAuth2UserInfo - 구현 클래스

    import com.example.rest.security.oauth2.userinfo.OAuth2UserInfo;
    
    import java.util.Map;
    
    public class GithubOAuth2UserInfo extends OAuth2UserInfo {
        public GithubOAuth2UserInfo(Map<String, Object> attributes) {
            super(attributes);
        }
    
        @Override
        public String getId() {
            return ((Integer)attributes.get("id")).toString();
        }
    
        @Override
        public String getName() {
            return (String) attributes.get("name");
        }
    
        @Override
        public String getEmail() {
            return (String) attributes.get("email");
        }
    
        @Override
        public String getImageUrl() {
            return (String) attributes.get("avatar_url");
        }
    }

     

     

    FacebookOAuth2UserInfo - 구현 클래스

    import com.example.rest.security.oauth2.userinfo.OAuth2UserInfo;
    
    import java.util.Map;
    
    public class FacebookOAuth2UserInfo extends OAuth2UserInfo {
        public FacebookOAuth2UserInfo(Map<String, Object> attributes) {
            super(attributes);
        }
    
        @Override
        public String getId() {
            return (String) attributes.get("id");
        }
    
        @Override
        public String getName() {
            return (String) attributes.get("name");
        }
    
        @Override
        public String getEmail() {
            return (String) attributes.get("email");
        }
    
        @Override
        public String getImageUrl() {
            // 페이스북 이미지 URL > picture:{data:{url:""}}
            if(attributes.containsKey("picture")){
                Map<String, Object> pictureObj = (Map<String, Object>) attributes.get("picture");
                if(pictureObj.containsKey("data")){
                    Map<String, Object> dataObj = (Map<String, Object>) attributes.get("data");
                    if(dataObj.containsKey("url")){
                        return (String) dataObj.get("url");
                    }
                }
            }
            return null;
        }
    }

     

     

    OAuth2UserInfoFactory - 인증 이후 정보를 OAuth2UserInfo 클래스로 매핑

    import com.example.rest.model.AuthProvider;
    import com.example.rest.security.oauth2.userinfo.social.FacebookOAuth2UserInfo;
    import com.example.rest.security.oauth2.userinfo.social.GithubOAuth2UserInfo;
    import com.example.rest.security.oauth2.userinfo.social.GoogleOAuth2UserInfo;
    
    import java.util.Map;
    
    public class OAuth2UserInfoFactory {
        public static OAuth2UserInfo getOAuth2UserInfo(String registrationId, Map<String, Object> attributes) {
            if(registrationId.equalsIgnoreCase(AuthProvider.google.toString())) {
                return new GoogleOAuth2UserInfo(attributes);
            } else if (registrationId.equalsIgnoreCase(AuthProvider.facebook.toString())) {
                return new FacebookOAuth2UserInfo(attributes);
            } else if (registrationId.equalsIgnoreCase(AuthProvider.github.toString())) {
                return new GithubOAuth2UserInfo(attributes);
            } else {
                throw new OAuth2AuthenticationProcessingException("Sorry! Login with " + registrationId + " is not supported yet.");
            }
        }
    }

     

     

    OAuth2AuthenticationProcessingException - 인증 예외

    import org.springframework.security.core.AuthenticationException;
    
    public class OAuth2AuthenticationProcessingException extends AuthenticationException {
        public OAuth2AuthenticationProcessingException(String msg, Throwable t) {
            super(msg, t);
        }
    
        public OAuth2AuthenticationProcessingException(String msg) {
            super(msg);
        }
    }