BE/Spring

[Spring Security] 네이버 로그인하기

멍목 2022. 6. 6. 22:16
반응형

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

https://inf.run/tcLk

 

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

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

www.inflearn.com


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

https://ajdahrdl.tistory.com/247

 

 

1. 네이버 로그인 준비

더보기

1) Google에서 '네이버 개발자 센터' 검색 후 네이버 개발자 센터.. 클릭

 

 

2) 로그인 후 상단의 Application - 애플리케이션 등록 메뉴로 이동

 

 

3) 초기 인증 후 API 신청 시, 자신의 상황에 맞게 설정 후 등록하기 클릭

 

 

4) client id와 client secret을 볼 수 있음

 

 

 

2. Spring Boot 설정

1) application.yml 네이버 관련 설정 추가

  security:
    oauth2:
      client:
        registration:
          # 구글 설정
          google:
            client-id: 발급받은 ID
            client-secret: 발급받은 secret
            scope:
              - email
              - profile
              
          # 페이스북 설정
          facebook:
            client-id: 발급받은 ID
            client-secret: 발급받은 secret
            scope:
              - email
              - public_profile
              
          # 네이버 설정
          naver:
            client-id: 발급받은 ID
            client-secret: 발급받은 secret
            scope:
              - name
              - email
            #- profile_image
            client-name: Naver
            authorization-grant-type: authorization_code                  # oauth2의 동작 방식은 여러가지가 있는데, 코드를 응답받는 방식으로 진행한다는 의미
            redirect-uri: http://localhost:8080/login/oauth2/code/naver   # naver의 경우 redirect-uri를 설정해줘야함. (google, facebook의 경우 디폴트로 설정되어 있음)

        # 네이버의 경우, 따로 provider 설정을 추가해줘야 한다.
        provider:
          # 아래의 링크들은 네이버 로그인 개발 가이드에 있다.
          naver:
            authorization-uri: https://nid.naver.com/oauth2.0/authorize
            token-uri: https://nid.naver.com/oauth2.0/token
            user-info-uri: https://openapi.naver.com/v1/nid/me
            user-name-attribute: response                               #회원정보를 json으로 받는데 response라는 키 값으로 네이버가 리턴해줄 것이다.

 

 

2) 네이버 로그인 시점에 사용할 NaverUserInfo.java 추가

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

import java.util.Map;

public class NaverUserInfo implements OAuth2UserInfo {

    private Map<String, Object> attributes;         // oauth2User.getAttributes()

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

 

 

3) PrincipalOauth2UserSerivce에 Naver 로직 추가

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.NaverUserInfo;
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;

import java.util.Map;

@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 if(platform.equals("naver")){
            System.out.println("naver를 이용한 로그인");
            oAuth2UserInfo = new NaverUserInfo((Map)oAuth2User.getAttributes().get("response"));    // response를 가져와서 넣어주는 이유: 우리가 필요한 건 naver측에서 보내줄 때 response 안에 담아서 보내주기 때문임
        }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());
    }
}

 

반응형