ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Security - 페이스북 로그인
    Framework & Library/Spring Security 2021. 10. 4. 22:34

    API 설정

    프로젝트생성

     

    ㆍ 페이스북 개발자 홈페이지에 접속을 한 후 위 사진에 표시된 "내 앱" 버튼을 클릭한다.

     

     

    ㆍ "내 앱"에 접속한 후 "앱 만들기" 버튼을 클릭한다.

     

     

    ㆍ 앱 유형을 "없음"으로 선택한 후 "다음" 버튼을 누른다.

     

     

    ㆍ 표시 이름을 spring-security-basic으로 정한 후 "앱 만들기" 버튼을 클릭한다.

     

     

    ㆍ 앱을 만든 후 Facebook 로그인 "설정" 버튼을 클릭한다.

     

     

    ㆍ 설정에 들어온 뒤 "웹" 버튼을 클릭한다.

     

     

    ㆍ 사이트 URL을 "http://localhost:8080"으로 설정한 후 "Save" 버튼을 눌러 저장한다.

     

     

    ㆍ 설정 카테고리의 "기본 설정" 버튼을 누른 후 앱 ID와 앱 시크릿 코드를 확인하고 프로젝트 생성을 마무리한다.


    Spring Security 설정

    application.yml 파일 수정

     

    ㆍ application.yml 파일에 위 코드를 추가하여 페이스북 로그인을 위한 설정을 마무리한다.

    ㆍ client-id와 client-secret에는 페이스북 개발자 홈페이지에서 발급받은 앱 ID와 앱 시크릿 코드를 적는다.

     

    loginForm.html 수정

     

    ㆍ loginForm.html 파일에 페이스북 로그인을 수행할 수 있는 코드를 추가한다.

    ㆍ "/oauth2/authorization/facebook" 주소는 OAuth Client 라이브러리를 사용하여 페이스북 로그인을 수행하기 위해 고정된 주소이다.


    테스트

    로그인 페이지

     

    ㆍ 서버를 실행하고, 로그인 페이지에 접속한 후 페이스북 로그인 링크를 클릭한다.

     

    페이스북 로그인 페이지

     

    ㆍ 페이스북 로그인 링크에 접속한 후 본인의 페이스북 계정을 통해 페이스북 로그인을 수행한다.

     

    로그인 결과 확인

     

    ㆍ 로그인을 수행한 후 페이스북 로그인을 수행한 사용자의 정보가 콘솔 창에 잘 출력되고 있음을 확인할 수 있다.


    소셜 로그인 별 사용자 정보의 관리

    소셜 로그인 별 사용자 정보 관리의 필요성

    ㆍ 구글 로그인과 페이스북 로그인 수행 시 전달받는 사용자 정보의 형태가 다르다.

    ㆍ 그렇기 때문에 소셜 로그인의 종류마다 별도의 클래스를 만들어 관리를 해주어야 한다.

    ㆍ 또한, 네이버와 카카오 같은 소셜 로그인 기능을 추가할 경우 유지보수가 훨씬 쉬워진다는 장점이 있다.

     

    OAuth2UserInfo 인터페이스 생성
    public interface OAuth2UserInfo {
        String getProviderId();
    
        String getProvider();
    
        String getEmail();
    
        String getName();
    }

    ㆍ oauth 패키지에 provider 패키지를 생성한 후 OAuth2UserInfo 인터페이스를 생성한다.

    ㆍ 소셜 로그인 별로 사용자의 정보를 받기 위한 인터페이스를 위 코드와 같이 작성한다.

     

    GoogleUserInfo 클래스 생성
    public class GoogleUserInfo implements OAuth2UserInfo {
    
        private Map<String, Object> attributes;   // oAuth2User.getAttributes()
    
        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");
        }
    }

    provider 패키지 내에 구글 로그인을 수행한 사용자의 정보를 받기 위한 클래스인 GoogleUserInfo를 생성한다.

    ㆍ 클래스를 생성한 후 OAuth2UserInfo 인터페이스를 구현하고 메서드들을 오버라이딩하는 방식이다.

     

    FacebookUserInfo 클래스 생성
    public class FacebookUserInfo implements OAuth2UserInfo {
    
        private Map<String, Object> attributes;   // oAuth2User.getAttributes()
    
        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");
        }
    }

    ㆍ FacebookUserInfo 클래스 또한 GoogleUserInfo 클래스와 동일한 방식으로 생성한다.

     

    PrincipalOauth2UserService 수정
    @Override
    /* 구글로부터 받은 userRequest 데이터를 후처리하는 함수 */
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException {
    
        System.out.println("getClientRegistration : " + userRequest.getClientRegistration());   // registrationId로 어떤 OAuth로 로그인 헸는지 확인 가능
        System.out.println("getAccessToken : " + userRequest.getAccessToken());
    
        OAuth2User oAuth2User = super.loadUser(userRequest);
    
        System.out.println("getAttributes : " + oAuth2User.getAttributes());
    
        /* 소셜 로그인 수행시 강제 회원가입 */
        OAuth2UserInfo oAuth2UserInfo = null;
    
        if (userRequest.getClientRegistration().getRegistrationId().equals("google")) {
            System.out.println("Google 로그인 요청");
            oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
        } else if (userRequest.getClientRegistration().getRegistrationId().equals("facebook")) {
            System.out.println("Facebook 로그인 요청청");
            oAuth2UserInfo = new FacebookUserInfo(oAuth2User.getAttributes());
        } else {
            System.out.println("Google, Facebook 로그인만 지원합니다.");
        }
        
        String provider = oAuth2UserInfo.getProvider();   // ex) google
        String provideId = oAuth2UserInfo.getProviderId();  // ex) 103163902666771091884
        String username = provider + "_" + provideId;   // ex) google_103163902666771091884
        String password = encoder.encode("겟인데어");
        String email = oAuth2UserInfo.getEmail();
        String role = "ROLE_USER";
    
        User userEntity = userRepository.findByUsername(username);
    
        if (userEntity == null) {
            userEntity = User.builder()
                    .username(username)
                    .password(password)
                    .email(email)
                    .role(role)
                    .provider(provider)
                    .providerId(provideId)
                    .build();
    
            userRepository.save(userEntity);
        } else {
            System.out.println("소셜 계정으로 회원가입을 한 상태입니다.");
        }
    
        return new PrincipalDetails(userEntity, oAuth2User.getAttributes());
    }

    ㆍ PrincipalOauth2UserService 클래스 내의 loadUser() 메서드를 위 코드와 같이 수정한다.

    ㆍ 메서드 내에 OAuth2UserInfo 객체를 선언하고, 소셜 로그인 종류별로 객체를 생성하여 로그인 사용자의 정보를 처리한다.

     

    소셜 로그인 별 사용자 확인

     

    ㆍ 로그인 페이지에서 구글 로그인, 페이스북 로그인, 일반 로그인을 한 사용자의 정보가 DB에 제대로 저장이 되었는지 확인해 본다.

    ㆍ 로그인 방식 별로 사용자의 정보가 DB에 잘 저장되었음을 확인할 수 있다.


     

    GitHub - qlsdud0604/spring-security-basic: 스프링 시큐리티의 기초를 학습하는 공간

    스프링 시큐리티의 기초를 학습하는 공간. Contribute to qlsdud0604/spring-security-basic development by creating an account on GitHub.

    github.com

     

    728x90

    댓글

Designed by Tistory.