[https://developers.kakao.com/docs/latest/ko/kakaologin/common](kakao developers)
kako developers에 접속한다
일단 로그인 할라면 토큰을 달라고 해!
그러면 토큰 줘서 로그인 되는 과정!
두번의 과정을 거쳐야 함!!
REST API로 간다!
API 응답한 결과 형식이 -> JSON, XML로 나온다
응답 형식을 받을 자바 객체가 필요하다!!
JSON에서 전달하는 값과 동일한 객체들을 class로 생성을 해주는 것!
KakaoTokenResponse.java
package com.test.api.web.model;
public class KakaoTokenResponse {
String token_type;
String access_token;
String id_token;
int expires_in;
String refresh_token;
int refresh_token_expires_in;
String scope;
public String getToken_type() {
return token_type;
}
public void setToken_type(String token_type) {
this.token_type = token_type;
}
public String getAccess_token() {
return access_token;
}
public void setAccess_token(String access_token) {
this.access_token = access_token;
}
public String getId_token() {
return id_token;
}
public void setId_token(String id_token) {
this.id_token = id_token;
}
public int getExpires_in() {
return expires_in;
}
public void setExpires_in(int expires_in) {
this.expires_in = expires_in;
}
public String getRefresh_token() {
return refresh_token;
}
public void setRefresh_token(String refresh_token) {
this.refresh_token = refresh_token;
}
public int getRefresh_token_expires_in() {
return refresh_token_expires_in;
}
public void setRefresh_token_expires_in(int refresh_token_expires_in) {
this.refresh_token_expires_in = refresh_token_expires_in;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
@Override
public String toString() {
return "KakaoTokenResponse [token_type=" + token_type + ", access_token=" + access_token + ", id_token="
+ id_token + ", expires_in=" + expires_in + ", refresh_token=" + refresh_token
+ ", refresh_token_expires_in=" + refresh_token_expires_in + ", scope=" + scope + "]";
}
}
KakaoAuthResponse.java
package com.test.api.web.model;
public class KakaoAuthResponse {
String code;
String error;
String error_description;
String state;
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getError_description() {
return error_description;
}
public void setError_description(String error_description) {
this.error_description = error_description;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
@Override
public String toString() {
return "KakaoAuthResponse [code=" + code + ", error=" + error + ", error_description=" + error_description
+ ", state=" + state + "]";
}
}
토큰을 받아와야 한다.
KakaoLoginService.java
package com.test.api.web.service;
import java.util.HashMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.test.api.util.RestApiUtilXml;
import com.test.api.web.model.KakaoAuthResponse;
import com.test.api.web.model.KakaoTokenResponse;
@Service
public class KakaoLoginService {
private static final Logger logger = LoggerFactory.getLogger(KakaoLoginService.class);
private static final String CLIENTID = "c35e5b43ffd51c99cec8a9e0e250d353";
public KakaoTokenResponse getToken(KakaoAuthResponse response) {
String url = "https://kauth.kakao.com/oauth/token";
HashMap<String, String> data = new HashMap<String, String>();
data.put("client_id", CLIENTID);
data.put("redirect_uri", "http://localhost:8090/authResult");
data.put("grant_type", "authorization_code");
data.put("code", response.getCode());
HashMap<String , String> headerData = new HashMap<String, String>();
headerData.put("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
KakaoTokenResponse tokenResult = RestApiUtilXml.connHttpGetType(url, data, headerData, KakaoTokenResponse.class);
logger.info("token result : {}",tokenResult.toString());
return tokenResult;
}
}
KakaoLoginController
package com.test.api.web.controller;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.test.api.web.model.KakaoAuthResponse;
import com.test.api.web.service.KakaoLoginService;
@Controller
public class KakaoLoginController {
private static final Logger logger = LoggerFactory.getLogger(KakaoLoginController.class);
@Autowired
KakaoLoginService kakaoLoginService;
@RequestMapping(value="/",method = RequestMethod.GET)
public String loginView() {
return "login";
}
@RequestMapping(value="/authResult", method = RequestMethod.GET)
public String authResult(KakaoAuthResponse response) {
logger.info("success auth-code:{} ",response.getCode());
kakaoLoginService.getToken(response);
return "main";
}
}
util !! 파싱해주는 부분이 필요하다
package com.test.api.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.util.HashMap;
import javax.net.ssl.HttpsURLConnection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RestApiUtil {
private static final Logger log = LoggerFactory.getLogger(RestApiUtil.class);
// http 연결을 하기 위해 url, 요청 파라미터, 헤더 파라미터, 응답할 데이터 형식 전달 필요
public static <T> T ConnHttpGetType(String connUrl, HashMap<String, String> data,
HashMap<String, String> headerData, Class<T> classType){
try {
// 문자열 동적 처리
StringBuilder urlBuilder = new StringBuilder(connUrl); // URL
// 반복 횟수 체크할 변수
int count =0;
// Get방식의 파라미터 전달 반법 : url?name =aaa&age=10
for(String key:data.keySet()) {
if(count ==0) {
urlBuilder.append("?"+URLEncoder.encode(key,"utf-8")+"="+URLEncoder.encode(data.get(key),"utf-8"));
}else {
urlBuilder.append("&"+URLEncoder.encode(key,"utf-8")+"="+URLEncoder.encode(data.get(key),"utf-8"));
}
count ++;
}
// api에서 원하는 헤더 데이터를 연결
if(urlBuilder.toString().startsWith("https")) {
System.out.println("https");
return JsonUtil.parseJson(RestApiUtil.httpsConn(urlBuilder.toString(), headerData), classType);
}else {
System.out.println("http");
return JsonUtil.parseJson(RestApiUtil.httpConn(urlBuilder.toString(), headerData), classType); }
} catch (Exception e) {
log.error("ConnHttpGetType Error : {}",e);
return null;
}
}
private static String httpsConn(String connUrl, HashMap<String, String> headerData) throws IOException {
URL url = new URL(connUrl);
System.out.println(url);
// 서비스를 요청할 API에 필요한 요청 파라미터를 전달.
HttpURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setRequestMethod("GET");
for(String key:headerData.keySet()) {
conn.setRequestProperty(key, headerData.get(key));
}
// 텍스트 기반의 데이터를 읽을 떄 사용되눈 객체
BufferedReader rd;
// 응답 성공
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// 응답 실패
} else {
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
conn.disconnect();
System.out.println(sb.toString());
return (sb.toString());
}
private static String httpConn(String connUrl, HashMap<String, String> headerData) throws IOException {
URL url = new URL(connUrl);
// 서비스를 요청할 API에 필요한 요청 파라미터를 전달.
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setRequestMethod("GET");
for(String key:headerData.keySet()) {
conn.setRequestProperty(key, headerData.get(key));
}
// 텍스트 기반의 데이터를 읽을 떄 사용되눈 객체
BufferedReader rd;
// 응답 성공
if(conn.getResponseCode() >= 200 && conn.getResponseCode() <= 300) {
rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// 응답 실패
} else {
rd = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
}
StringBuilder sb = new StringBuilder();
String line;
while ((line = rd.readLine()) != null) {
sb.append(line);
}
rd.close();
conn.disconnect();
return (sb.toString());
}
}