프로젝트에 OAuth2를 적용하지 않은 상태에서 카카오 로그인을 적용하려고 합니다.
아래 과정들은 기본적인 동작을 정리한 것이니 자세한 적용은 API문서를 확인 하시면 됩니다.
Kakao Developers 클라이언트 키 발급
kakao developers(링크)에 접속하여 카카오 계정으로 로그인을 하고
상단 '내 애플리케이션'에 들어가서 애플리케이션 추가 버튼을 눌러 추가해줍니다.
추가하면 아래쪽에 애플리케이션이 추가됩니다.
이 앱을 클릭하여 들어가보면 좌측에 '요약정보' 메뉴가 있고, 눌러보면 REST API키를 확인할 수 있습니다.
카카오 로그인 ON
그리고 카카오 로그인을 사용하기 위해 왼쪽 메뉴에서 카카오 로그인을 눌러주고, ON을 해줍니다.
Redirect할 URI도 적어줍니다.
인가코드 요청하기
인가 코드를 받는 주소는 /kakao/oauth 로 정하였기 때문에 위 사진과는 1번 경로가 다르다.
@Controller
@RequestMapping("/kakao")
public class KakaoController
// 서비스 생략
public KakaoController() {
}
@GetMapping(value = "/oauth")
public String kakaoConnect() {
StringBuffer url = new StringBuffer();
url.append("https://kauth.kakao.com/oauth/authorize?");
url.append("client_id=" + 받은 RESTAPI 키);
url.append("&redirect_uri=http://localhost:8080/kakao/callback");
url.append("&response_type=code");
return "redirect:" + url.toString();
}
}
또한 이 url에 이전에 작성한 Redirect URI도 작성을 해주어야 한다.
받은 인가 코드로 토큰 발급 요청
@RequestMapping(value = "/callback", produces="application/json", method = {RequestMethod.GET, RequestMethod.POST})
public String kakaoLogin(@RequestParam("code") String code, RedirectAttributes ra,
HttpSession session, HttpServletResponse response, Model model) throws IOException {
Map<String, String> tokens = getKakaoAccessToken(code);
session.setAttribute("access_token", tokens.get("access_token"));
return null;
}
public Map<String, String> getKakaoAccessToken(String code) {
String accessToken = "";
RestTemplate restTemplate = new RestTemplate();
String reqUrl = "/oauth/token";
URI uri = URI.create("https://kauth.kakao.com" + reqUrl);
HttpHeaders headers = new HttpHeaders();
MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
param.set("grant_type", "authorization_code");
param.set("client_id", 발급받은 API 키);
param.set("redirect_uri", "http://localhost:8080/kakao/callback");
param.set("code", code);
HttpEntity<MultiValueMap<String, Object>> restRequest = new HttpEntity<>(param, headers);
ResponseEntity<JSONObject> apiResponse = restTemplate.postForEntity(uri, restRequest, JSONObject.class);
JSONObject responseBody = apiResponse.getBody();
HashMap<String, String> tokens = new HashMap<>();
accessToken = (String) responseBody.get("access_token");
String refreshToken = (String) responseBody.get("refresh_token");
tokens.put("access_token", accessToken);
tokens.put("refresh_token", refreshToken);
return tokens;
}
인가 코드를 받으면 /callback으로 전달하고, getKakaoAccessToken() 메소드를 사용하여 토큰을 받습니다.
getKakaoAccessToken() 메소드에서는 토큰을 받기 위해서 요청을 보내야하는데, 아래와 같이 양식을 따라야 합니다.
따라서 이에 맞게 param을 설정하여, header 와 함께 HttpEntity를 만들어줍니다.
그리고 요청 uri에 /oauth/token으로 요청을 던집니다.
정상적으로 response 되면, access_token과 refresh_token 모두 가져올 수 있습니다.
사용자 정보 가져오기
이렇게 가져온 token으로 사용자 정보를 가져와야 합니다.
그냥 가져오게 되면 json 객체에는 id와 connected_at만 존재하게 됩니다.
회원정보 관리를 위해 닉네임을 따로 가져오겠습니다.
좌측 '동의항목'에서 닉네임 설정을 눌러줍니다.
닉네임이 필수로 사용되므로 '필수 동의'와 '동의 목적'을 작성하였습니다.
@RequestMapping(value = "/callback", produces="application/json", method = {RequestMethod.GET, RequestMethod.POST})
public String kakaoLogin(@RequestParam("code") String code, RedirectAttributes ra,
HttpSession session, HttpServletResponse response, Model model) throws IOException {
// ..생략
JSONObject userInfo = getKakaoUserInfo(tokens.get("access_token"));
return null;
}
private JSONObject getKakaoUserInfo(String access_token) {
RestTemplate restTemplate = new RestTemplate();
String reqUrl = "/v2/user/me";
URI uri = URI.create("https://kapi.kakao.com" + reqUrl);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + access_token);
HttpEntity<MultiValueMap<String, Object>> restRequest = new HttpEntity<>(headers);
ResponseEntity<JSONObject> apiResponse = restTemplate.postForEntity(uri, restRequest, JSONObject.class);
JSONObject responseBody = apiResponse.getBody();
return responseBody;
}
요청 양식에 따라 headers에 추가해주고, 똑같이 restTemplate을 이용해서 전달해주고 가져오면 됩니다.
로그아웃
@GetMapping(value = "/logout")
public void kakaoLogout(HttpSession session) {
String accessToken = (String) session.getAttribute("access_token");
RestTemplate restTemplate = new RestTemplate();
String reqUrl = "/v1/user/logout";
URI uri = URI.create(KAKAO_HOST_URI + reqUrl);
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + accessToken);
HttpEntity<MultiValueMap<String, Object>> restRequest = new HttpEntity<>(headers);
ResponseEntity<JSONObject> apiResponse = restTemplate.postForEntity(uri, restRequest, JSONObject.class);
session.removeAttribute("access_token");
}
로그아웃 양식에 따라 동일하게 요청을 보내줍니다.
이렇게하면 어플리케이션에 발급받은 토큰이 만료되고, session에서 토큰을 지웁니다.
브라우저 상에서 카카오 계정이 로그아웃 되지는 않고, 어플리케이션 내에서만 로그아웃됩니다.
참고자료
'TOOL > SPRING' 카테고리의 다른 글
스프링 MVC에서 요청을 처리하는 과정 (0) | 2023.09.13 |
---|---|
STS4 에서 Darkest Dark Theme 쓰기(일반 설치가 안되는 경우 수동설치) (4) | 2023.06.02 |
STS3 에서 Darkest Dark Theme 쓰기(feat. 인텔리제이 테마) (3) | 2023.05.23 |
남에게 설명할 때 비로소 자신의 지식이 된다.
포스팅이 도움되셨다면 하트❤️ 또는 구독👍🏻 부탁드립니다!! 잘못된 정보가 있다면 댓글로 알려주세요.