이 글을 이상한 통신 오류로 날려버린 내 4시간에 바칩니다ㅜ
셋팅 정보 : Spring, REST API, thymeleaf
build gradle
에 Spring 프로젝트와 관련한 의존성 외 응답값을 JSON 형식으로 받기 위한 json-simple 라이브러리를 추가했다.
implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1.1'
REST API 키 발급을 위해 카카오 사이트에 방문하여 로그인한다.
Kakao Developers 사이트
로그인을 하고 우측 상단의 내 애플리케이션에 들어가 테스트 할 애플리케이션을 등록한다.
우리가 필요한건 REST API 키!
메뉴 중 플랫폼을 선택하여 Web 플랫폼 등록을 선택한다.
기본 도메인 등록!
인가 코드를 받을 Redirect URI 등록한다.
로그인 활성화 상태를 ON으로 바꾼다.
Redirect URI를 설정한다.
동의 항목에서 수집할 사용자의 정보를 선택한다.
나는 사용자의 닉네임, 이메일, 연령대를 가져올래요
그리고 로그아웃에 대한 설정도 해줬다.
카카오 로그인은 발급받은 REST API 키로 사용자의 유효성을 검증하고 인가 코드를 Redirect URI에 등록된 곳으로 반환한다.
이 인가 코드를 이용해 토큰을 발급 받고 나면 사용자 정보와 같은 내용을 조회 할 수 있다.
추가로 메뉴에서 도구 > 리소스 다운로드 > 카카오 로그인으로 가면 아이콘을 다운받을 수 있다.
아이콘 다운로드
구현을 위한 나의 파일 디렉토리 구조이다.
다운로드 한 로그인 아이콘 이미지는 images 폴더 안에 넣었다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<a href="https://kauth.kakao.com/oauth/authorize?client_id=발급받은 키 복붙하기&redirect_uri=http://localhost:8090/login/kakao&response_type=code">
<img src="images/kakao_login_large_narrow.png">
</a>
</body>
</html>
client_id= 뒤에 발급받은 REST API KEY 값을 넣어준다.
이미지 경로랑 이름 확인해서 적기
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<th:if test="${userId eq null}">
<a href="https://kauth.kakao.com/oauth/logout?client_id=발급받은 키 복붙하기&logout_redirect_uri=http://localhost:8090/login">로그아웃</a>
</a>
</th:if>
<th:if test="${userId ne null}">
<h1>로그인 성공입니다</h1>
<h2 th:text="${session.nickname}"></h2>
<h2 th:text="${session.email}"></h2>
<h2 th:text="${session.age_range}"></h2>
</th:if>
</body>
</html>
여기도 client_id= 뒤에 발급받은 REST API KEY 값을 넣어준다.
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.stereotype.Service;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.ProtocolException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
@Service
public class KakaoService {
public String getToken(String code) throws IOException {
// 인가코드로 토큰받기
String host = "https://kauth.kakao.com/oauth/token";
URL url = new URL(host);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
String token = "";
try {
urlConnection.setRequestMethod("POST");
urlConnection.setDoOutput(true); // 데이터 기록 알려주기
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(urlConnection.getOutputStream()));
StringBuilder sb = new StringBuilder();
sb.append("grant_type=authorization_code");
sb.append("&client_id=발급받은 키 값");
sb.append("&redirect_uri=http://localhost:8090/login/kakao");
sb.append("&code=" + code);
bw.write(sb.toString());
bw.flush();
int responseCode = urlConnection.getResponseCode();
System.out.println("responseCode = " + responseCode);
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line = "";
String result = "";
while ((line = br.readLine()) != null) {
result += line;
}
System.out.println("result = " + result);
// json parsing
JSONParser parser = new JSONParser();
JSONObject elem = (JSONObject) parser.parse(result);
String access_token = elem.get("access_token").toString();
String refresh_token = elem.get("refresh_token").toString();
System.out.println("refresh_token = " + refresh_token);
System.out.println("access_token = " + access_token);
token = access_token;
br.close();
bw.close();
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
return token;
}
public Map<String, Object> getUserInfo(String access_token) throws IOException {
String host = "https://kapi.kakao.com/v2/user/me";
Map<String, Object> result = new HashMap<>();
try {
URL url = new URL(host);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestProperty("Authorization", "Bearer " + access_token);
urlConnection.setRequestMethod("GET");
int responseCode = urlConnection.getResponseCode();
System.out.println("responseCode = " + responseCode);
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line = "";
String res = "";
while((line=br.readLine())!=null)
{
res+=line;
}
System.out.println("res = " + res);
JSONParser parser = new JSONParser();
JSONObject obj = (JSONObject) parser.parse(res);
JSONObject kakao_account = (JSONObject) obj.get("kakao_account");
JSONObject properties = (JSONObject) obj.get("properties");
//String id = obj.get("id").toString();
String email = kakao_account.get("email").toString();
String nickname = properties.get("nickname").toString();
String age_range = kakao_account.get("age_range").toString();
//result.put("id", id);
result.put("email", email);
result.put("nickname", nickname);
result.put("age_range", age_range);
br.close();
} catch (IOException | ParseException e) {
e.printStackTrace();
}
return result;
}
public String getAgreementInfo(String access_token)
{
String result = "";
String host = "https://kapi.kakao.com/v2/user/scopes";
try{
URL url = new URL(host);
HttpURLConnection urlConnection = (HttpURLConnection)url.openConnection();
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Authorization", "Bearer "+access_token);
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line = "";
while((line=br.readLine())!=null)
{
result+=line;
}
int responseCode = urlConnection.getResponseCode();
System.out.println("responseCode = " + responseCode);
// result is json format
br.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (ProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
여기도 발급받은 key 값을 넣어주고, redirect_uri도 설정한대로 알맞게 넣어준다.
import com.start.kakao.service.KakaoService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.Map;
@RequiredArgsConstructor
@Controller
@RequestMapping("/login")
public class KakaoCotroller{
@Autowired
KakaoService kakaoService;
@GetMapping("")
public String loginPage()
{
return "login";
}
@GetMapping("/kakao")
public String getCI(@RequestParam String code, Model model, HttpSession session) throws IOException {
System.out.println("code = " + code);
String access_token = kakaoService.getToken(code);
Map<String, Object> userInfo = kakaoService.getUserInfo(access_token);
model.addAttribute("code", code);
model.addAttribute("access_token", access_token);
model.addAttribute("userInfo", userInfo);
//값 꺼내오기위한 처리
if(model.getAttribute("userInfo") != null){
session.setAttribute("nickname", userInfo.get("nickname"));
session.setAttribute("email", userInfo.get("email"));
session.setAttribute("age_range", userInfo.get("age_range"));
}
return "index";
}
}
이렇게하면 카카오 로그인 api 끄으ㅡㅡㅡㅅ