이번 포스팅에서는 앞서 공부했던 OAuth 2.0 기반의 카카오 로그인 Api를 직접 호출해볼것이다.
spring:
profiles:
include: API-KEY
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: 아이디
password: 비밀번호
url: jdbc:mysql://localhost:3306/oAuth?serverTimezone=UTC&characterEncoding=UTF-8
jpa:
hibernate:
ddl-auto: create
properties:
hibernate:
format_sql: true
logging:
level:
org.hibernate.sql: debug
package com.example.loginApiStudy.Controller;
import com.example.loginApiStudy.Service.KakaoService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequiredArgsConstructor
public class kakaoLoginController {
private final KakaoService kakaoService;
@Value("${kakao-client-id}")
private String KAKAO_CLIENT_KEY;
@GetMapping("/")
public String home(Model model) {
model.addAttribute("apiKey", KAKAO_CLIENT_KEY);
return "home";
}
}
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a th:href="@{https://kauth.kakao.com/oauth/authorize(response_type='code',client_id=${apiKey}
,redirect_uri='http://localhost:8080/login/kakao')}">
Kakao 로그인
</a>
</body>
</html>
package com.example.loginApiStudy.Service;
import com.example.loginApiStudy.KakaoDTO;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.http.HttpHeaders;
import java.util.List;
@Service
@RequiredArgsConstructor
public class KakaoService {
String access_Token="";
String refresh_Token ="";
String authorizeURL = "https://kauth.kakao.com/oauth/token";
String resourceURL = "https://kapi.kakao.com/v2/user/me";
@Value("${kakao-client-id}")
private String KAKAO_CLIENT_KEY;
public String getKakaoAccessToken(String code) throws Exception {
if (code == null) throw new Exception("Faild get code");
try {
URL url = new URL(authorizeURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// POST 요청 설정
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// URL 파라미터 값 설정
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");
sb.append("&client_id=" + KAKAO_CLIENT_KEY); // TODO REST_API_KEY 입력
sb.append("&redirect_uri=http://localhost:8080/login/kakao"); // TODO 인가코드 받은 redirect_uri 입력
sb.append("&code=" + code);
bw.write(sb.toString());
bw.flush();
// 요청 결과 코드 확인
int responseCode = conn.getResponseCode();
System.out.println("responseCode : " + responseCode);
//요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
System.out.println("response body : " + result);
// JSON 파싱을 통해 Access Token 및 Refresh Token 추출
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
access_Token = element.getAsJsonObject().get("access_token").getAsString();
refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString();
System.out.println("access_Token: " + access_Token);
System.out.println("refresh_Token: " + refresh_Token);
br.close();
bw.close();
return access_Token;
} catch (Exception e) {
throw new Exception("API call failed");
}
}
public void receiveKakaoUser(String token) throws Exception {
if(token == null) throw new Exception("failed get Id_Token");
try {
URL url = new URL(resourceURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Authorization", "Bearer " + token);
int responseCode = conn.getResponseCode();
System.out.println("responseCode : " + responseCode);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
String[] str = result.split(",");
for (String i: str) {
System.out.println(i);
}
System.out.println("response body : " + result);
//Gson 라이브러리로 JSON파싱
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
Long id = element.getAsJsonObject().get("id").getAsLong();
boolean hasEmail = element.getAsJsonObject().get("kakao_account").getAsJsonObject().get("has_email").getAsBoolean();
String email = "";
if (hasEmail) {
email = element.getAsJsonObject().get("kakao_account").getAsJsonObject().get("email").getAsString();
}
String nickname = element.getAsJsonObject().get("properties").getAsJsonObject().get("nickname").getAsString();
System.out.println("id : " + id);
System.out.println("email : " + email);
System.out.println("nickname : " + nickname);
br.close();
} catch (Exception e) {
throw new Exception("API call failed");
}
}
}
@GetMapping("/login/kakao")
public void kakaoCallBack(@RequestParam String code) throws Exception {
System.out.println(code);
String kakaoAccessToken = kakaoService.getKakaoAccessToken(code);
kakaoService.receiveKakaoUser(kakaoAccessToken);
}
호출이 잘 된 것을 확인할 수 있었다.
api 응답과 호출 과정을 공부하고 직접 호출을 해보면서 http의 헤더 부분을 공부할 수 있었다. 우리가 쓰던 html은 body 부분일 뿐이었고, header는 지금까지 알고 있던 것보다 더 다양한 역할을 하고 있던 것을 확인할 수 있었다. 코드를 짜는 것도 당연히 중요하지만 시스템 아키택처와 CS를 열심히 공부해야겠다고 생각했다. 다음 포스팅에서는 호출한 정보를 데이터베이스에 저장시킬 것이다.