BE/Spring

[Spring Security] 페이스북 로그인하기

멍목 2022. 6. 3. 22:58
반응형

이 포스팅은 아래의 강의를 참고하였으니 여기에서 공부하시는 것을 추천드립니다.

https://inf.run/tcLk

 

[무료] 스프링부트 시큐리티 & JWT 강의 - 인프런 | 강의

스프링부트 시큐리티에 대한 개념이 잡힙니다., - 강의 소개 | 인프런...

www.inflearn.com


이전 포스팅과 이어지는 내용입니다.

https://ajdahrdl.tistory.com/246

 

 

 

1. 페이스북 로그인 준비

더보기

1) Google에서 '페이스북 api 콘솔' 검색 후 페이스북 개발자 사이트.. 클릭

 

 

 

2) 우측 상단의 '시작하기' → 페이스북 로그인 → 내 앱 → 앱 만들기

 

 

 

3) 앱 유형은 '없음', 표시 이름은 자유롭게 설정 후 앱 만들기 완료

 

 

4) Facebook 로그인 기능을 사용할 것이기에 Facebook 로그인의 설정 버튼 클릭

 

5) 아래의 정보를 참고하여 설정 완료

  • 앱의 플랫폼: 웹
  • 사이트 URL: http://localhost:8080
  • 나머지는 무시해도 무관(Spring Security & OAuth2를 이용할 것이기에)

 

 

6) '설정 - 기본 설정' 에서 앱 ID 와 앱 시크릿코드를 확인

 

 

2. Spring Boot 설정

1) pom.xml에 아래의 의존성(OAuth2 Client) 추가 및 application.yml에 아래처럼 설정

- pom.xml: OAuth2 Client 의존성이 이미 있으면 무시

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>

 

- application.yml 

spring:
  security:
    oauth2:
      client:
        registration:
          facebook:
            client-id: ID입력
            client-secret: 시크릿코드 입력
            scope:
            - email
            - public_profile

 

 

2) 구글과 페이스북 로그인 차이점

providerId가 다르다. (google="sub", facebook="id")

인터페이스를 이용하여 유지보수가 간편하도록 소스를 작성한다.

 

a) OAuth2UserInfo 인터페이스 생성

package com.cos.security1.config.oauth2.provider;

public interface OAuth2UserInfo {
    String getProviderId();     // pk
    String getProvider();       // google, facebook, etc
    String getEmail();
    String getName();
}

 

 

b) GoogleUserInfo 인터페이스 생성

package com.cos.security1.config.oauth2.provider;

import java.util.Map;

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");
    }
}

 

 

 

c) FacebookUserInfo 인터페이스 생성

package com.cos.security1.config.oauth2.provider;

import java.util.Map;

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");
    }
}

 

 

d) PrincipalOauth2UserService 수정

package com.cos.security1.config.oauth2;

import com.cos.security1.Repository.UserRepository;
import com.cos.security1.config.auth.PrincipalDetails;
import com.cos.security1.config.oauth2.provider.FacebookUserInfo;
import com.cos.security1.config.oauth2.provider.GoogleUserInfo;
import com.cos.security1.config.oauth2.provider.OAuth2UserInfo;
import com.cos.security1.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.oauth2.client.userinfo.DefaultOAuth2UserService;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserRequest;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.user.OAuth2User;
import org.springframework.stereotype.Service;

@Service
public class PrincipalOauth2UserSerivce extends DefaultOAuth2UserService {

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private UserRepository userRepository;

    // 구글 로그인 작동 방식
    // 구글로그인버튼 클릭 > 구글로그인 > code 리턴(OAuth-Client Library) > AccessToken 요청
    // userRequest 정보 > loadUser함수 호출 > 구글로부터 회원 프로필을 받아줌

    // 구글로부터 받은 userRequest 데이터에 대한 후처리 함수
    // 함수 종료 시, @AuthenticationPrincipal 어노테이션이 만들어진다.
    // OAuth2 로그인 시 사용
    @Override
    public OAuth2User loadUser(OAuth2UserRequest userRequest) throws OAuth2AuthenticationException{
        System.out.println("getClientRegistration: "+userRequest.getClientRegistration());  // registration: 어떤 매체에서 로그인했는지 확인 가능
        System.out.println("getAccessToken: "+userRequest.getAccessToken().getTokenValue());    // access token
        System.out.println("getAttributes: "+super.loadUser(userRequest).getAttributes());      // 프로필 정보

        OAuth2User oAuth2User = super.loadUser(userRequest);
        System.out.println("getAttributes: "+oAuth2User.getAttributes());

        String platform = userRequest.getClientRegistration().getRegistrationId();        // google, facebook, etc
        OAuth2UserInfo oAuth2UserInfo = null;

        if(platform.equals("google")){
            System.out.println("Google을 이용한 로그인");
            oAuth2UserInfo = new GoogleUserInfo(oAuth2User.getAttributes());
        }else if(platform.equals("facebook")){
            System.out.println("Facebook을 이용한 로그인");
            oAuth2UserInfo = new FacebookUserInfo(oAuth2User.getAttributes());
        }else{
            System.out.println("다른 플랫폼임. 지원 X");
        }
        String provider = oAuth2UserInfo.getProvider();
        String providerId = oAuth2UserInfo.getProviderId();

        // OAuth2 로그인 시, username과 password는 필요없지만 형식상 넣어줌
        String username = provider + "_" + providerId;
        System.out.println("username: "+username);
        String password = bCryptPasswordEncoder.encode("provider");
        String role = "ROLE_USER";
        String email = oAuth2UserInfo.getEmail();

        User findUser = userRepository.findByUsername(username);

        if(findUser == null){
            findUser = User.builder()
                    .username(username)
                    .password(password)
                    .email(email)
                    .role(role)
                    .provider(provider)
                    .providerId(providerId)
                    .build();

            userRepository.save(findUser);
        }

        return new PrincipalDetails(findUser, oAuth2User.getAttributes());
    }
}
반응형