네이버 API 로그인 구현하기

Yeoonnii·2022년 11월 22일
0

Project

목록 보기
5/6
post-thumbnail

API 이용신청

네이버 개발자 센터 - NAVER Developers

  1. API 신청

  2. 필요한 정보 선택

  3. 서비스 URL, Callback URL 설정

  • 서비스 URL : 실제 운영하고 있는 사이트 주소
  • Callback URL : 네이버 로그인, 정보 제공 동의 과정 완료 후 code값과 state 값을 문자열로 전송받을 URL
  1. 내 애플리케이션에서 Client ID, Client Secret를 확인할 수 있다


네이버 API 공통 가이드

네이버 오픈API 공통 가이드
로그인 방식 오픈 API 호출 - 샘플 코드
네이버 로그인 API 명세



[Vue.js] 네이버 로그인 화면구현


1. index.html에 Naver SDK를 추가해준다

  • SDK란?
    어떤 소프트웨어를 만들기 위한 도구 모음! API는 SDK의 일부가 될 수 있다
    = SDK가 API보다 더 큰 개념!
    참고링크

public/index.html

<script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script>

2. 기존 로그인 화면에 네이버 로그인 로직 구현

MemberLoginPage.vue

<template>에 네이버 로그인 버튼<div> 추가

<!-- 네이버 로그인 버튼 노출 영역 -->
            <img src="../../assets/images/naver_login.png" @click="naverLogin" />

로그인 페이지로 이동할 url 설정

        // 네이버 로그인을 위한 url 이동 
        const naverLogin = () => {
            const url = `https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=${state.naverClientId}&redirect_uri=${state.callbackUrl}&state=${state.states}`;

            console.log("==================url====================");
            console.log(url);

            window.location.href=url;
        };   



vue.config.js

서버 주소 설정 후 서버를 재구동 해줘야 적용된다

const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
  transpileDependencies: true,
  devServer : {
    proxy : {
      "/ROOT" : {
        target : 'http://127.0.0.1:8080/',
        changeOrigin : true,
        logLevel : 'debug'
      },
    "/oauth2.0" : {
      target : 'https://nid.naver.com/',
      changeOrigin : true,
      logLevel : 'debug'
    },
    "/v1" : {
      target : 'https://openapi.naver.com/',
      changeOrigin : true,
      logLevel : 'debug'
    },
  },
    port : 9090
  }
})


3. 콜백페이지 생성

LoginNCallback.vue

  • 콜백 페이지 이동시 접근 토큰 발급 요청
  • 요청 후 받아온 정보를 DB에 저장
  • DB 저장 후 메인으로 이동
<template>
    <div>

    </div>
</template>

<script>
import { onMounted } from '@vue/runtime-core';
import axios from 'axios';
import { useRoute, useRouter } from 'vue-router';
import { useStore } from 'vuex';

export default {
    setup () {
      const route = useRoute();
      const router = useRouter();
      const store = useStore();

      const state = ({
        naverClientId : 'Wg77gLgzjURrRdBDfnhx',
        clientSecret : 'jIesIkc7SG',
        callbackUrl : 'http://localhost:9090/naver_callback',
        code : route.query.code,
        states : route.query.state, // csrf 공격을 방지하기 위해 애플리케이션에서 생성한 상태 토큰값으로 URL 인코딩을 적용한 값을 사용
        access_token : "", // 발급받은 access_token 저장을 위한 변수
        refresh_token : "", // 발급받은 refresh_token 저장을 위한 변수
        userid    :'',
        userpw    :'',
        role      : 'CUSTOMER',
        birth     :'', // DB에 넣을 생일
        birthday  :'', // 가공할 생일 정보
        birthyear :'', // 가공할 연도 정보
        nickname  :'',
        phone     :'',
        apiimageurl : ''
      })

      // callback url
      const naverCallback = async() => {
        console.log('route.query.code => ', route.query.code); //파라미터로 전달받은 code값
        console.log('route.query.states => ', route.query.state); //파라미터로 전달받은 state값

        
        const url = `/oauth2.0/token?grant_type=authorization_code&client_id=${state.naverClientId}&client_secret=${state.clientSecret}&code=${state.code}&state=${state.states}`;
        const headers = {"X-Naver-Client-Id": state.naverClientId, "X-Naver-Client-Secret": state.clientSecret};
        const { data } = await axios.get(url, {headers});
        
        console.log("data => " , data);
        
        console.log("data.access_token => " , data.access_token);
        state.access_token = data.access_token
        
        console.log("data.refresh_token => " , data.refresh_token);
        state.refresh_token = data.refresh_token 
        
        naverUserInfo();
      }
      
      // 사용자 정보 전달받기
      const naverUserInfo = async() => {
        const url = `/v1/nid/me`;
        let header = "Bearer " + state.access_token;
        const headers = {"Authorization": header};
        console.log("headers => ", headers);
        const { data } = await axios.get(url, { headers });
        console.log("*****naverUserInfo data***** => ", data);
        
        // 변수에 값 넣기
        state.userid = data.response.email;
        state.nickname = data.response.nickname;
        state.apiimageurl = data.response.profile_image;
        
        // 생일 쪼개기
        let birtharr = data.response.birthday.split('-');
        state.birthday = birtharr.join('');
        state.birthyear = data.response.birthyear.substring(2);
        state.birth = state.birthyear + state.birthday

        // 휴대폰 번호 쪼개기
        let phonearr = data.response.mobile.split('-');
        state.phone = phonearr.join('');

        naverUseridCheck(data);
      }
      
      // 회원가입시 아이디(이메일) 중복여부 확인
      const naverUseridCheck = async() => {
        const url = `/ROOT/api/member/idcheck.json?userid=${state.userid}`;
        const headers = {"Content-Type":"application/json"};
        const { data } = await axios.get(url,{headers});
        console.log('이메일중복확인 data=>' ,data);

        if(data.result === true){ //DB에 일치하는 아이디가 존재하는 경우
            naverUserLogin() // 회원가입 안하고 로그인 진행
        } else { //DB에 일치하는 아이디가 존재하지 않는 경우
          naverUserJoin(); //회원가입 후 로그인 진행
        }
      }

      // 회원가입 
      const naverUserJoin = async() => {
        // 변수에 값 넣기
        // state.userid = data2.response.email;
        // state.nickname = data2.response.nickname;
        // state.apiimageurl = data2.response.profile_image;

        const url = `/ROOT/api/member/join.json`;
        const headers = {"Content-Type":"application/json"};
        const body = {
            userid : state.userid,
            userpw : state.userpw,
            role : state.role,
            birth : state.birth,
            nickname : state.nickname,
            phone : state.phone
        }
        const { data } = await axios.post(url, body, {headers});
        console.log(data);
        if(data.status === 200){
            alert('회원가입완료');
        }
        naverUserJoinImg();
      }

      // 회원 프로필 사진 저장
      const naverUserJoinImg = async() => {
        const url = `/ROOT/api/memberimage/apiinsert.json`;
        const headers = {"Content-Type":"application/json"};
        
        const member1 = {
          userid : state.userid
        }
        const body = {
          member : member1,
          apiimageurl : state.apiimageurl
        }
        const response = await axios.post(url, body, {headers});
        console.log(response);
        naverUserLogin();
      }

      // 로그인처리 + 토큰발행
      const naverUserLogin = async() => {
        const url = `/ROOT/api/member/login.json`;
        const headers = { "Content-Type": "application/json" };
        const body = {
                userid: state.userid,
                userpw: state.userpw,
                role: 'CUSTOMER'
            }
        const { data } = await axios.post(url, body, { headers });
        console.log(data);
            if (data.status === 200) {
                sessionStorage.setItem("token", data.result);

                store.commit('setLogged', true);
                store.commit('setCounter');

                router.push({ path: '/' });
            }
      }    

      onMounted(()=> {
        naverCallback();
      })

        return {state, naverCallback}
    }
}
</script>

<style lang="scss" scoped>

</style>



로그인 철회

네이버ID - 이력관리 - 연결된 서비스 관리 에서 테스트시 회원가입했던 서비스 동의를 철회할 수 있다

0개의 댓글