인가 코드(code)
를 받음code
에 대한 토큰(Access Token)
을 받음(String getAccessToken(String code)
)Access Token
으로부터 필요한 정보 추출(HashMap<String, Object> getUserInfo(String accessToken)
)index.html
: 홈화면<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>치얌이는 코딩 중</title>
</head>
<body>
<li>
<a href="/home">Kakao Login</a>
</li>
</body>
</html>
login.html
: 로그인 화면<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<h1>Kakao Login</h1>
<span th:if="${userId==null}">
<a href="https://kauth.kakao.com/oauth/authorize?client_id=${CLITENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=code"> //본인 걸로 수정하기
<img src = "/icon/kakao_login_medium_narrow.png">
</a>
</span>
<span th:if="${userId!=null}">
<form name="logout" action="http://localhost:8080/logout">
<input type="submit" value="로그아웃">
</form>
</span>
</body>
</html>
LoginService.java
getAccessToken
:"https://kauth.kakao.com/oauth/token"
로부터 AccessToken
받기getUserInfo
: "https://kapi.kakao.com/v2/user/me"
로부터 필요한 정보(profile_nickname
, profile_image
, account_email
) 받기logout
: "http://kapi.kakao.com/v1/user/logout"
로부터 응답 받아내기package gan.missulgan.service;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import org.apache.tomcat.util.json.JSONParser;
import org.springframework.stereotype.Service;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
@Service
public class LoginService {
public String getAccessToken(String code) throws IOException {
//인가코드로 토큰 받기
String accessToken = "";
String refreshToken = "";
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=${CLITENT_ID}"); //본인 걸로 수정하기
sb.append("&redirect_uri=${REDIRECT_URI}"); //본인 걸로 수정하기
sb.append("&code="+code);
bw.write(sb.toString());
bw.flush();
//결과 코드가 200이라면 성공
int responseCode = conn.getResponseCode();
System.out.println("response code = " + responseCode);
//JSON 파싱
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);
accessToken = element.getAsJsonObject().get("access_token").getAsString();
refreshToken = element.getAsJsonObject().get("refresh_token").getAsString();
br.close();
bw.close();
} catch (Exception e) {
e.printStackTrace();
}
return accessToken;
}
public HashMap<String, Object> getUserInfo(String accessToken) throws IOException {
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.setRequestProperty("Authorization", "Bearer " + accessToken);
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 kakaoAccount = element.getAsJsonObject().get("kakao_account").getAsJsonObject();
String profile_nickname = properties.getAsJsonObject().get("nickname").getAsString();
String profile_image = properties.getAsJsonObject().get("profile_image").getAsString();
String account_email = kakaoAccount.getAsJsonObject().get("email").getAsString();
userInfo.put("profile_nickname", profile_nickname);
userInfo.put("profile_image", profile_image);
userInfo.put("account_email", account_email);
} catch (Exception e) {
e.printStackTrace();
}
return userInfo;
}
public void logout(String accessToken) {
String reqURL = "http://kapi.kakao.com/v1/user/logout";
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setRequestProperty("Authorization", "Bearer " + accessToken);
int responseCode = conn.getResponseCode();
System.out.println("responseCode = " + responseCode);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String result = "";
String line = "";
while((line = br.readLine()) != null) {
result+=line;
}
System.out.println(result);
} catch (Exception e) {
e.printStackTrace();
}
}
}
LoginController.java
구현createLoginForm
: 홈 화면에서 로그인 화면으로 이동login
: 인증코드 요청 -> 인증코드로 토큰 접근 -> 로그인 정보 접근logout
: 토큰 정보 삭제, model 정보 삭제package gan.missulgan.controller;
import java.io.IOException;
import java.util.HashMap;
import javax.servlet.http.HttpSession;
import gan.missulgan.service.LoginService;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
import static org.springframework.web.bind.annotation.RequestMethod.*;
@Controller
public class LoginController {
LoginService loginService = new LoginService();
/**
* 홈에서 로그인 화면으로 이동
*/
@GetMapping("/home")
public String createLoginForm() {
return "login";
}
/**
* 로그인
*/
@RequestMapping(value = "/login", method = GET)
public ModelAndView login(@RequestParam("code") String code, HttpSession session) throws IOException {
ModelAndView mav = new ModelAndView();
// 1번 인증코드 요청 전달
String accessToken = loginService.getAccessToken(code);
// 2번 인증코드로 토큰 전달
HashMap<String, Object> userInfo = loginService.getUserInfo(accessToken);
System.out.println("login info : " + userInfo.toString());
if(userInfo.get("account_email") != null) {
session.setAttribute("userId", userInfo.get("account_email"));
session.setAttribute("accessToken", accessToken);
}
mav.addObject("userId", userInfo.get("account_email"));
mav.setViewName("login");
return mav;
}
/**
* 로그아웃
*/
@RequestMapping(value = "/logout", method = GET)
public ModelAndView logout(HttpSession session) {
ModelAndView mav = new ModelAndView();
loginService.logout((String)session.getAttribute("accessToken"));
session.removeAttribute("accessToken");
session.removeAttribute("userId");
mav.setViewName("login");
return mav;
}
}
로그인 첫 화면
카카오 로그인
클릭 시
로그아웃
클릭 시