본문 바로가기
Spring/Spring Boot

[Spring boot - OAuth2] Kakao Login 구현 #04

by seoyamin 2022. 11. 21.

0. 전체 Flow

오늘은  Step 3  부분을 구현해보고자 한다. 

 

①  Access Token을 이용하여 Kakao Auth Server에게 사용자 정보 요청
②  사용자 정보 받기

 

 

1.  OAuthService 구현

♠  Kakao Developers Docs

우리는 결국 https://kauth.kakao.com/oauth/token 으로 POST 요청을 보내서 사용자 정보를 받으면 된다.

카카오 공식 문서에 request, response와 관련된 형식이 안내되어 있다.

 

▷ 꺼내올 데이터
RESPONSE의 id 데이터
RESPONSE의 properties에 담긴 nickname 데이터

RESPONSE의 kakao_account에 담긴 email 데이터

 

나는 어떤 분의 블로그 글을 참고하여 코드를 작성 및 공부하였다. 

( 출처 https://suyeoniii.tistory.com/81 )

전체 코드를 한번 훑어보고, 하나하나 뜯어보며 이해해보자.

 

// OAuthService.java

package com.surveasy.surveasy.service;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;

@Service
public class OAuthService {

    public String getKakaoAccessToken(String code) {
        String access_Token = "";
        String refresh_Token = "";
        String reqURL = "https://kauth.kakao.com/oauth/token";

        try {
            
            // 지난번에 작성했던 Access Token 발급 함수
            
        }  catch (IOException e) {
            e.printStackTrace();
        }

        return access_Token;
    }


    public HashMap<String, Object> createKakaoUser(String token) {

        HashMap<String, Object> userInfo = new HashMap<String, Object>();
        String reqURL = "https://kapi.kakao.com/v2/user/me";

        try {
            URL url = new URL(reqURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setRequestMethod("POST");
            conn.setDoOutput(true);
            conn.setRequestProperty("Authorization", "Bearer " + token);  // header 작성, access token 전달

            // 결과 코드가 200이면 성공
            int responseCode = conn.getResponseCode();
            System.out.println("response CODE : " + responseCode);

            // 요청을 통해 얻은 JSON 타입의 Response 데이터 읽어오기
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = "";
            String result = "";

            while((line = bufferedReader.readLine()) != null) {
                result += line;
            }
            System.out.println("response BODY : " + result);

            // GSON 라이브러리로 JSON 파싱
            JsonParser jsonParser = new JsonParser();
            JsonElement jsonElement = jsonParser.parse(result);

            JsonObject properties = jsonElement.getAsJsonObject().get("properties").getAsJsonObject();
            JsonObject kakao_account = jsonElement.getAsJsonObject().get("kakao_account").getAsJsonObject();


            int id = jsonElement.getAsJsonObject().get("id").getAsInt();
            boolean hasEmail = kakao_account.get("has_email").getAsBoolean();

            String nickname = properties.getAsJsonObject().get("nickname").getAsString();
            userInfo.put("nickname", nickname);

            String email = "";
            if(hasEmail) {
                email = kakao_account.get("email").getAsString();
                userInfo.put("email", email);
            }


            System.out.println("id : " + id);
            System.out.println("email : " + email);
            System.out.println("nickname : " + nickname);

            bufferedReader.close();


        } catch (IOException e) {
            e.printStackTrace();
        }

        return userInfo;
    }

}

 

1-1. 변수 설정

우리가 받아올 nickname, email을 담을 해시맵 userInfo를 초기화 하고, 요청을 보낼 request URI 주소도 정의해놓는다. 

 

HashMap<String, Object> userInfo = new HashMap<String, Object>();
String reqURL = "https://kapi.kakao.com/v2/user/me";

 

 

1-2. http connection 열기

2-1에서 정의한 reqest URI에 POST 요청을 보내기 위해 http connection을 정의하고,

사용을 위해 스위치를 켜준다. (setDoOutput 값을 false → true로 변경)

이때, 헤더에는 다양한 인증 타입을 가진 토큰들 중 어떤 종류인지를 알려주는 정보를 담아서 보내야 한다.

우리가 사용할 토큰 타입은 Bearer로, JWT 혹은 OAuth와 관련된 토큰 종류라고 한다.

 

URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Authorization", "Bearer " + token);  // header 작성, access token 전달
// 결과 코드가 200이면 성공
int responseCode = conn.getResponseCode();
System.out.println("response CODE : " + responseCode);

 

 

1-3.  요청 결과를 JSON 타입으로 읽어오기

stream으로 받아온 string 데이터들을 gson 라이브러리를 통해 JSON Object 형태로 파싱한다.

 

// 요청을 통해 얻은 JSON 타입의 Response 데이터 읽어오기
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";

while((line = bufferedReader.readLine()) != null) {
    result += line;
}
System.out.println("response BODY : " + result);

// GSON 라이브러리로 JSON 파싱
JsonParser jsonParser = new JsonParser();
JsonElement jsonElement = jsonParser.parse(result);

 

 

1-4.  id , nickname , email 꺼내기

1-3에서 만들어낸 object에서 id, nickname, email을 꺼낸다.

이때, 사용한 bufferedReader, bufferedWriter는 close 해준다. 

 

JsonObject properties = jsonElement.getAsJsonObject().get("properties").getAsJsonObject();
JsonObject kakao_account = jsonElement.getAsJsonObject().get("kakao_account").getAsJsonObject();


int id = jsonElement.getAsJsonObject().get("id").getAsInt();
boolean hasEmail = kakao_account.get("has_email").getAsBoolean();

String nickname = properties.getAsJsonObject().get("nickname").getAsString();
userInfo.put("nickname", nickname);

String email = "";
if(hasEmail) {
    email = kakao_account.get("email").getAsString();
    userInfo.put("email", email);
}


System.out.println("id : " + id);
System.out.println("email : " + email);
System.out.println("nickname : " + nickname);

bufferedReader.close();

 

 

 

2. OAuthController에서 결과 확인

OAuthController에서 userInfo 해시맵을 완성하고, 결과를 확인해보자!

 

//  OAuthController.java

package com.surveasy.surveasy.controller;

import com.surveasy.surveasy.service.OAuthService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;

@RestController
@RequiredArgsConstructor
public class OAuthController {

    private final OAuthService oAuthService;


    @ResponseBody
    @GetMapping("/kakao")
    public void kakaoCallBack(@RequestParam String code) {
        String access_Token = oAuthService.getKakaoAccessToken(code);
        // System.out.println(access_Token);

        HashMap<String, Object> userInfo = oAuthService.createKakaoUser(access_Token);
        System.out.println(userInfo);
    }
}

 

RUN하고 프론트를 통해 카카오 로그인을 해본 결과, 이메일과 닉네임을 잘 받아온 것을 확인할 수 있다 !