스프링 프레임워크에서 카카오 로그인 REST API 사용하기!
스프링 프레임워크에서 카카오 로그인 REST API사용하는 방법!
- 참고사항(필독!)
- 프로젝트가 다 끝나고 기억나는대로 정리하는거라 import 내용이 틀릴 수 있음.
- 카카오에서 갖고오는 정보는 사용자 이름(ex 카톡 이름), 사용자 이메일만 갖고오는 코드.
- 카카오 개발자 센터에서 redirect_uri 등 기본적인것들은 먼저 설정하셔야 합니다.
- REST API KEY를 사용함.
- 플랫폼 Web & 사이트 도메인 설정을 해야함.
- Redirect URI 설정을 해야함.
- 설정 방법은 생략하겠습니다. 직접 찾아서 해보세요.
- 아직 학생이고 배우는중이라 제가 올린 정보가 정확하지 않습니다! 참고용으로만 보세요.
- DB에 저장하는 방법은 나중에 나중에 올리겠습니다.
- Kakao Developers
- 참고 사이트
사용자가 카카오 API를 호출함.
카카오 서버가 호출됨.
로그인 정보를 입력받음.
문제가 없을 시 카카오 서버는 redirect_uri로 인증 코드(code)를 넘겨줌.
사용자는 받은 인증 코드로 카카오 서버에 토큰(access_Token)을 요청함.
카카오 서버에서 토큰을 넘겨줌
받은 토큰을 카카오 서버에 보내 로그인한 사용자 정보를 요청함.
카카오 서버에서 토큰을 받고 그에 맞는 사용자 정보를 보냄
정보를 받아 처리
여기서 redirect_uri이란 jsp주소가 아닌 컨트롤러 메서드의 value값입니다.
카카오 및 네이버에서 넘겨주는 사용자 정보는 JSON 타입입니다.
JSON안에 담겨있는 정보의 타입은 String 타입으로 담겨있습니다.
※위 내용은 제가 공부하며 정리한 것으로 실제 내용과 다를 수 있습니다!
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<!-- 카카오 로그인 -->
<a class="p-2" href="https://kauth.kakao.com/oauth/authorize?client_id=REST_API키&redirect_uri=REDIRECT_URL&response_type=code">
<!-- REST_API키 및 REDIRECT_URi는 본인걸로 수정하세요 -->
<!-- 저는 redirect_uri을 http://localhost:8080/member/kakaoLogin로 했습니다. -->
<!-- 본인걸로 수정 시 띄어쓰기 절대 하지 마세요. 오류납니다. -->
<img src="/resources/icon/kakao_login_large_narrow.png" style="height:60px">
<!-- 이미지는 카카오 개발자센터에서 제공하는 login 이미지를 사용했습니다. -->
</a>
</body>
</html>
package com.spring.project.controller;
import java.io.IOException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
@Controller
@RequestMapping(value="/member/*")
public class MemberController {
@RequestMapping(value="/kakaoLogin", method=RequestMethod.GET)
public String kakaoLogin(@RequestParam(value = "code", required = false) String code) throws Exception {
System.out.println("#########" + code);
return "member/testPage";
/*
* 리턴값의 testPage는 아무 페이지로 대체해도 괜찮습니다.
* 없는 페이지를 넣어도 무방합니다.
* 404가 떠도 제일 중요한건 #########인증코드 가 잘 출력이 되는지가 중요하므로 너무 신경 안쓰셔도 됩니다.
*/
}
}
여기까지 만들고 로그인을 했을 때 카카오 로그인 창이 뜨며 로그인시 아래처럼 코드가 넘어옴.
// 결과 예시, 아래와 똑같은 값이 나오는 것이 아닌 아래처와 같은 형식으로 나온다는 것임.
#########GJ0ouweigBr9fDyCfu-SsfZVjY69LOz0SDS2xJat1bMecBZeBAthQGQD-gSoac-2GqYyHgorDKcAAAFzarIl2g
package com.spring.project.controller;
import java.io.IOException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.spring.project.service.MemberService;
@Controller
@RequestMapping(value="/member/*")
public class MemberController {
@Autowried
private MemberService ms;
@RequestMapping(value="/kakaoLogin", method=RequestMethod.GET)
public String kakaoLogin(@RequestParam(value = "code", required = false) String code) throws Exception {
System.out.println("#########" + code);
// 위에서 만든 코드 아래에 코드 추가
String access_Token = ms.getAccessToken(code);
System.out.println("###access_Token#### : " + access_Token);
return "member/testPage";
}
}
package com.spring.project.service;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import org.springframework.stereotype.Service;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@Service
public class MemberService {
public String getAccessToken (String authorize_code) {
String access_Token = "";
String refresh_Token = "";
String reqURL = "https://kauth.kakao.com/oauth/token";
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
// POST 요청을 위해 기본값이 false인 setDoOutput을 true로
conn.setRequestMethod("POST");
conn.setDoOutput(true);
// POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");
sb.append("&client_id=REST_API키"); //본인이 발급받은 key
sb.append("&redirect_uri=REDIRECT_URI"); // 본인이 설정한 주소
sb.append("&code=" + authorize_code);
bw.write(sb.toString());
bw.flush();
// 결과 코드가 200이라면 성공
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);
// Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성
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();
} catch (IOException e) {
e.printStackTrace();
}
return access_Token;
}
}
통신 결과가 200이여야 성공인겁니다. 200이 아니면 통신 오류입니다.
// 결과 예시, 아래와 똑같은 값이 나오는 것이 아닌 아래와 같은 형식으로 나온다는 것임.
// responseCode가 200이 아닐 시 통신에 실패했다는 것으로 다시 확인해보세요.
responseCode : 200
response body : {"access_token":"LilJmueUBPlH6pIuAnEra6igTiRllke-n6RnFQo9dZwAAAFzatW0ew","token_type":"bearer","refresh_token":"zHKhaFpAmDXwNJmSLa-wdwvx4g69Rt6CrP_qgQo9dZwAAAFzatW0eg","expires_in":21599,"scope":"account_email profile","refresh_token_expires_in":5183999}
access_token : LilJmueUBPlH6pIuAnEra6igTiRllke-n6RnFQo9dZwAAAFzatW0ew
refresh_token : zHKhaFpAmDXwNJmSLa-wdwvx4g69Rt6CrP_qgQo9dZwAAAFzatW0eg
###access_Token#### : LilJmueUBPlH6pIuAnEra6igTiRllke-n6RnFQo9dZwAAAFzatW0ew
package com.spring.project.controller;
import java.io.IOException;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.spring.project.service.MemberService;
@Controller
@RequestMapping(value="/member/*")
public class MemberController {
@Autowried
private MemberService ms;
@RequestMapping(value="/kakaoLogin", method=RequestMethod.GET)
public String kakaoLogin(@RequestParam(value = "code", required = false) String code) throws Exception {
System.out.println("#########" + code);
String access_Token = ms.getAccessToken(code);
// 위에서 만든 코드 아래에 코드 추가
HashMap<String, Object> userInfo = ms.getUserInfo(access_Token);
System.out.println("###access_Token#### : " + access_Token);
System.out.println("###nickname#### : " + userInfo.get("nickname"));
System.out.println("###email#### : " + userInfo.get("email"));
return "member/testPage";
}
}
public HashMap<String, Object> getUserInfo(String access_Token) {
// 요청하는 클라이언트마다 가진 정보가 다를 수 있기에 HashMap타입으로 선언
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("GET");
// 요청에 필요한 Header에 포함될 내용
conn.setRequestProperty("Authorization", "Bearer " + access_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;
}
System.out.println("response body : " + result);
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
JsonObject properties = element.getAsJsonObject().get("properties").getAsJsonObject();
JsonObject kakao_account = element.getAsJsonObject().get("kakao_account").getAsJsonObject();
String nickname = properties.getAsJsonObject().get("nickname").getAsString();
String email = kakao_account.getAsJsonObject().get("email").getAsString();
userInfo.put("nickname", nickname);
userInfo.put("email", email);
} catch (IOException e) {
e.printStackTrace();
}
return userInfo;
}
위 코드까지 성공적으로 마쳤으면 로그인 시 정보를 얻어올 수 있을겁니다.
DB에 저장하는 코드는 차후에 기회가 되면 다루겠습니다.
// 결과 예시, 아래와 똑같은 값이 나오는 것이 아닌 아래와 같은 형식으로 나온다는 것임.
// responseCode가 200이 아닐 시 통신에 실패했다는 것으로 다시 확인해보세요.
// 이름과 이메일은 개인정보 보호를 위해 임의로 바꿨습니다.
// 실제로는 로그인한 사람의 이름과 이메일이 출력됩니다.
responseCode : 200
response body : {"access_token":"LilJmueUBPlH6pIuAnEra6igTiRllke-n6RnFQo9dZwAAAFzatW0ew","token_type":"bearer","refresh_token":"zHKhaFpAmDXwNJmSLa-wdwvx4g69Rt6CrP_qgQo9dZwAAAFzatW0eg","expires_in":21599,"scope":"account_email profile","refresh_token_expires_in":5183999}
access_token : LilJmueUBPlH6pIuAnEra6igTiRllke-n6RnFQo9dZwAAAFzatW0ew
refresh_token : zHKhaFpAmDXwNJmSLa-wdwvx4g69Rt6CrP_qgQo9dZwAAAFzatW0eg
###access_Token#### : LilJmueUBPlH6pIuAnEra6igTiRllke-n6RnFQo9dZwAAAFzatW0ew
###nickname#### : 하늘
###email#### : sky@gmail.com
정말 어 . 렵 . 습 . 니 . 다. 그러니 좌절하지마시고,
제가 종합한 내용으로 모두 성공하시면 좋겠습니다.
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<a class="p-2" href="https://kauth.kakao.com/oauth/authorize?client_id=REST_API키&redirect_uri=REDIRECT_URI&response_type=code">
<!-- REST_API키 및 REDIRECT_URI는 본인걸로 수정하세요 -->
<!-- 본인걸로 수정 시 띄어쓰기 절대 하지 마세요. 오류납니다. -->
<img src="/resources/icon/kakao_login_large_narrow.png" style="height:60px">
</a>
</body>
</html>
package com.spring.project.controller;
import java.io.IOException;
import java.util.HashMap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import com.spring.project.service.MemberService;
@Controller
@RequestMapping(value="/member/*")
public class MemberController {
@Autowried
private MemberService ms;
@RequestMapping(value="/kakaoLogin", method=RequestMethod.GET)
public String kakaoLogin(@RequestParam(value = "code", required = false) String code) throws Exception {
System.out.println("#########" + code);
String access_Token = ms.getAccessToken(code);
HashMap<String, Object> userInfo = ms.getUserInfo(access_Token);
System.out.println("###access_Token#### : " + access_Token);
System.out.println("###nickname#### : " + userInfo.get("nickname"));
System.out.println("###email#### : " + userInfo.get("email"));
return "member/testPage";
}
}
package com.spring.project.service;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import org.springframework.stereotype.Service;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
@Service
public class MemberService {
public String getAccessToken (String authorize_code) {
String access_Token = "";
String refresh_Token = "";
String reqURL = "https://kauth.kakao.com/oauth/token";
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");
sb.append("&client_id=REST_API키"); //본인이 발급받은 key
sb.append("&redirect_uri=REDIRECT_URI"); // 본인이 설정한 주소
sb.append("&code=" + authorize_code);
bw.write(sb.toString());
bw.flush();
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;
}
System.out.println("response body : " + result);
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();
} catch (IOException e) {
e.printStackTrace();
}
return access_Token;
}
public HashMap<String, Object> getUserInfo(String access_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("GET");
conn.setRequestProperty("Authorization", "Bearer " + access_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;
}
System.out.println("response body : " + result);
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
JsonObject properties = element.getAsJsonObject().get("properties").getAsJsonObject();
JsonObject kakao_account = element.getAsJsonObject().get("kakao_account").getAsJsonObject();
String nickname = properties.getAsJsonObject().get("nickname").getAsString();
String email = kakao_account.getAsJsonObject().get("email").getAsString();
userInfo.put("nickname", nickname);
userInfo.put("email", email);
} catch (IOException e) {
e.printStackTrace();
}
return userInfo;
}
}
사용자 정보까지는 불러와지는데 왜 닉네임이 깨져보일까요 ㅜㅜ