Criming
코딩으로 업삼기
Criming
전체 방문자
오늘
어제
  • 분류 전체보기 (29)
    • Programming (28)
      • Spring (5)
      • Database (2)
      • JSP (6)
      • Java (10)
      • 탐구 및 해결 (1)
      • 연습문제 (3)
      • 예제 (1)
    • 자격증 (0)
    • 기타 (1)
      • 블로그 운영 (0)
      • 문서 (1)

블로그 메뉴

  • 홈
  • 태그

공지사항

인기 글

태그

  • ASCII
  • Eclipse
  • jsp
  • forward
  • try-catch
  • Java SE
  • 아스키코드
  • Tomcat
  • println()
  • printf()
  • spring
  • 자바규칙
  • JDK
  • 표현언어
  • sendRedirect
  • ec2
  • param
  • Java EE
  • HttpuURLConnection
  • 인스턴스
  • aws
  • Escape문자
  • redirect
  • System.out
  • jre
  • json
  • print()
  • jvm
  • java
  • main()

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Criming

코딩으로 업삼기

Programming/Spring

[Spring] 카카오 Login API 사용하기

2022. 10. 26. 11:46

1. 기능설명

카카오톡 로그인 API 사용하기

 

(사전 설정) kakaoService.java ▶ 카카오 서버에서 클라이언트 인가코드로 토큰받는 메소드와 계정정보 받는 메소드

 

1) 서비스를 이용하는 클라이언트가 '카카오 로그인' 버튼을 클릭하여 요청하면, 카카오 계정으로 로그인해 사용자 동의를 거쳐 서비스 서버에서 카카오 서버로 [ 인가 코드 ] 를 요청한다. *카카오 로그인 세션은 기본 24시간이며, 로그인 상태 유지를 선택한 경우 한달이다.

 

2) 인가코드를 받아 토큰 받는 url로 요청하여 토큰 받기(토큰까지 받아야 로그인이 완료된다)

 

3) 해당 로그인한 클라이언트가 토큰을 받아 세션에 저장하여 유저 정보가 필요할때 요청하여 출력

 

4) 로그아웃시 세션에 저장된 토큰을 카카오 로그아웃 url로 넘겨 카카오 서버에서 로그아웃 처리


2. 추가한 라이브러리

Library  
Googel gson 토큰 값, 유저 정보을 gson 키&값 형태로 받기 위해


3. 카카오 API 기본설정하기

카카오 개발 홈페이지에서 회원가입 후 [ 내 애플리케이션 ] 에서  '애플리케이션' 추가하기(정보 수정가능함으로 편한 것으로 설정하기)

카카오 로그인은 서버간의 통신인 Rest API를 사용한다.

해당 키값을 사용하게 되고 로그인 과정의 이해가 필요하다면 홈페이지에 [문서] > [카카오 로그인] > [Rest API] 를 참고하면 된다.

 

0) 기본정보와 앱 키 확인하기 : 추가한 애플리케이션을 클릭하여 키값을 확인한다.

1) API 사용할 사이트 도메인 등록하기 : [ 해당 애플리케이션 ] > [ 플랫폼 ] > [ Web 도메인 등록하기]

2)  Redirect URL 등록하기 : 로그인 활성화(ON)하기, 로그인 버튼 클릭 후 넘어갈 Redirect URI 등록하기

3) 로그인 서비스 시작시 동의받을 항목 설정해주기( 예제에는 닉네임, 프로필 링크, 이메일 정보만 동의 받는다.)

*동의목적은 테스토용이라고 작성했다.

*동의화면 미리보기를 선택하면 설정한 동의항목들이 로그인 서비스시 어떻게 뜨는지 미리볼 수 있다.


4. 코드

[ 클라이언트 화면 ]

(login.jsp)

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<body>
	<c:choose>
		<c:when test="${empty sessionScope.id }">
			<form action="login" method="post" id="f">
				<input type="text" name="id" placeholder="아이디" /> <br> 
				<input type="password" name="pw" placeholder="비밀번호" /> <br> 
				 <br>
				<input type="submit" value="로그인"> <input type="button" value="취소"
					onclick="javascript:location.href='index'">
			</form>
			<br>
			<a href="https://kauth.kakao.com/oauth/authorize?
			client_id=Rest API 키값
			&redirect_uri=카카오 개발 홈페이지에서 설정한 Redirect URI
			&response_type=code">
				<img src="//k.kakaocdn.net/14/dn/btroDszwNrM/I6efHub1SN5KCJqLm1Ovx1/o.jpg"
				width="200" alt="카카오 로그인 버튼" />
			</a>
		</c:when>
		<c:otherwise>
			<p>
				${sessionScope.name }님 환영합니다.<br>
				<br> <a href="index">인덱스 페이지로 이동</a>
			</p>
		</c:otherwise>
	</c:choose>
</body>

카카오 로그인을 a태그에 링크를 걸어준다.

해당 링크는  인가코드 받는 형식의 url로 Rest API와 인가코드 넘겨 Redirect url로 설정해주어야 한다.

카카오 로그인 이미지는 카카오 개발 홈페이지에서  코드를 확인하거나 직접 파일을 다운받아 설정해주어도 된다.

 

(인가코드 받는 a태그 url 설정방법 자세히보기)

더보기

카카오 개발 홈페이지에서 [문서] > [카카오 로그인] > [Rest API] 에서 자세한 설정 방법들을 볼 수 있다.

 

'인가 코드 받기' 에서 Host 로 작성된 정보와 get 코드를 참고하여, url 은 아래 형태처럼 작성해주면 된다.

=> https://kauth.kakao.com/oauth/authorize?client_id=${REST_API_KEY}&redirect_uri=${REDIRECT_URL}&response_type=code

 

인가 코드를 받기위해 사전에 설정해야하는 것들도 볼 수있다.

 

인가 코드를 받기위해서 필수로 넘겨야하는 파라미터들을 볼 수 있다.

 

 

lgoin.jsp 페이지에서 카카오 로그인 서비스를 클릭하면 보이는 화면

 

(MemberController.java)

package com.care.db.basic.controller;

import java.util.HashMap;

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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import com.care.db.basic.dto.MemberDTO;
import com.care.db.basic.service.KakaoService;
import com.care.db.basic.service.MemberService;

@Controller
public class MemberController {
	@Autowired
	private MemberService service;

	@RequestMapping("index")
	public String index() {
		return "member/index";
	}

	// kakao login 기능
	// kakao 인가코드 발급은 설정한 Redirect URL로 문자형으로 String로 받아진다.
	@Autowired
	private KakaoService kakaoService;

	@GetMapping("kakaoLogin")
	public String kakaoLogin(String code) {
		System.out.println("인가 코드 : " + code);
		String accessToken = kakaoService.getAccessToken(code);
		HashMap<String, String> userInfo = kakaoService.getUserInfo(accessToken);
		System.out.println("이메일 : " + userInfo.get("email"));
		System.out.println("이름 : " + userInfo.get("nickname"));

		session.setAttribute("accessToken", accessToken);

		if (userInfo.isEmpty())
			return "member/login";
		return "member/index";
	}
	
	@GetMapping("login")
	public String login() {
		return "member/login";
	}

	@PostMapping("login")
	public String login(MemberDTO member, Model model) {
		String msg = service.login(member);
		model.addAttribute("msg", msg);
		if (msg.equals("로그인 성공"))
			return "member/index";
		return "member/login";
	}

	@RequestMapping("logout")
	public String logout(HttpSession session, Model model) {
		String accessToken = (String) session.getAttribute("accessToken");
		session.invalidate();
		model.addAttribute("msg", "로그 아웃");
		// kakao logout 기능
		if (accessToken != null)
			kakaoService.unlink(accessToken);
		return "member/logout";
	}
}

@GetMapping("kakaoLogin")public String kakaoLogin(String code){}

▶ Redirect URL로 설정한 Get매핑 메소드의매개변수 code는 '인가코드' 받는 변수이다.

▶ 받은 인가코드를 kakaoService.getAccessToken(code) 메소드를 통해 로그인한 토큰을 받는다.

     (로그아웃시 토큰이 필요하여 로그인시 회원마다 토큰 Session에 생성해준다.)

▶ 예제에서는 로그인 서비스 실행 후 필수사항 체크시 카카오 개발홈페이지에서 설정한 "필수항목인 프로필 사진, 닉네임과 선택사항인 이메일"을 선택하여 꼭 넘겨주어야한다. (kakaoService.java의 getUserInfo 메소드에서 리턴값으로 유저 닉네임과 이메일을 넘겨주기 때문에, 해당 사항들을 안넘겨주면 오류가 나므로 로그아웃 해주고 다시 로그인하여 체크해주어 넘겨주어야 한다.) 

 

@RequestMapping("logout")public String logout(HttpSession session, Model model) {}

▶ 로그아웃시 kakaoService.unlink(accessToken) 메소드를 통해 로그인시 Session에 생성해두었던 토큰을 주어 카카오 서버에서 로그아웃 처리할 수 있도록 해준다.

 

[ 사전설정 ]

(kakaoService.java)

package com.care.db.basic.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 java.util.HashMap;

import org.springframework.stereotype.Service;

import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;

@Service
public class KakaoService {
	// 매개변수 code는 인가코드
	public String getAccessToken(String code) {
		String accessToken = "";
		String reqURL = "https://kauth.kakao.com/oauth/token"; // 토큰 받는 카카오 url
		try {
			String sendMessage = "grant_type=authorization_code" + "&client_id=Rest API 키 값"
					+ "&redirect_uri=설정한 Redirect_uri" + "&code=" + code;

			URL url = new URL(reqURL); // POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
			HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 해당 URL로 웹 연결
			conn.setRequestMethod("POST"); // POST 메소드를 이용해서 데이터를 전달하기 위한 설정
			conn.setDoOutput(true); // POST 요청을 위해 기본값 false에서 setDoOutput을 true로 변경

			// 기본 outputStream을 통해 문자열로 처리할 수 있는 OutPutStreamWriter 변환 후 처리속도를 빠르게 하기위한
			// BufferedWriter로 변환해서 사용한다.
			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
			bw.write(sendMessage);
			bw.flush(); // 초기화

			int responseCode = conn.getResponseCode(); // 결과 코드가 200이라면 성공
			System.out.println("responseCode : " + responseCode);

			// 요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
			BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
			String line = "", result = "";
			while ((line = br.readLine()) != null) {
				result += line;
			}

			System.out.println("response body : " + result);
//			System.out.println("result.split : " + result.split(","));

			// Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성
			JsonElement element = JsonParser.parseString(result);
			accessToken = element.getAsJsonObject().get("access_token").getAsString();
			System.out.println("access_token : " + accessToken);

			br.close();
			bw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return accessToken;
	}

	public HashMap<String, String> getUserInfo(String accessToken) {
		HashMap<String, String> userInfo = new HashMap<String, String>();
		String reqURL = "https://kapi.kakao.com/v2/user/me";

		try {
			URL url = new URL(reqURL);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("POST");

			// 요청에 필요한 Header에 포함될 내용
			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);

			JsonElement element = JsonParser.parseString(result);
			JsonObject kakao_account = element.getAsJsonObject().get("kakao_account").getAsJsonObject();
			JsonObject profile = kakao_account.get("profile").getAsJsonObject();
			String nickname = profile.get("nickname").getAsString();
			String email = kakao_account.get("email").getAsString();

			userInfo.put("nickname", nickname);
			userInfo.put("email", email);

		} catch (IOException e) {
			e.printStackTrace();
		}
		return userInfo;
	}

	public void logout(String accessToken) {
		String reqURL = "https://kapi.kakao.com/v1/user/logout";

		URL url;
		try {
			url = new URL(reqURL);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("POST");
			// 요청에 필요한 Header에 포함될 내용
			conn.setRequestProperty("Authorization", "Bearer " + accessToken);
			int responseCode = conn.getResponseCode();
			System.out.println("responseCode : " + responseCode);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	/*
	 * 연결 끊기를 하면 로그아웃까지 진행됨.(동의항목 철회)
	 * https://developers.kakao.com/docs/latest/ko/kakaologin/common#link-and-unlink
	 * 연결끊기 https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#logout
	 */
	public void unlink(String accessToken) {
		String reqURL = "https://kapi.kakao.com/v1/user/unlink";
		URL url;
		try {
			url = new URL(reqURL);
			HttpURLConnection conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("POST");
			// 요청에 필요한 Header에 포함될 내용
			conn.setRequestProperty("Authorization", "Bearer " + accessToken);
			int responseCode = conn.getResponseCode();
			System.out.println("responseCode : " + responseCode);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

 

(토큰 받는 방법 자세히보기 -  getAccessToken메소드)

더보기

카카오 개발 홈페이지에서 [문서] > [카카오 로그인] > [Rest API] 에서 자세한 설정 방법들을 볼 수 있다.

'인가 코드 받기' 에서 Host 로 작성된 정보와 페이지 처리 방식을 참고하여, url 은 아래 형태처럼 작성해주면 된다.

 

예제에서는 아래 홈페이지 설정방식을 보고 토큰 받는 url 형태와 요청 메소드 형식인 Post 를 이와 같이 변수로 설정해주었다.

(HttpUrlConnection 객체 관련 메소드 설명 참고)

String reqURL = "https://kauth.kakao.com/oauth/token";
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);

 

토큰를 받기위해 사전에 설정해야하는 것들도 볼 수있다.

 

토큰 받는 url에 필수 적으로 넘겨야 하는 값은 아래와 같이 총 4가지이다.

필수로 넘겨주는 데이터를 문자열 변수 sendMessage에 저장했다.

 String sendMessage = "grant_type=authorization_code" + "&client_id=Rest API 키 값" + "&redirect_uri=설정한 Redirect_uri" + "&code=" + code;

 

토큰를 받기위해서 필수로 넘겨야하는 파라미터들을 볼 수 있다.

 

문자열 형태의 sendMessage를 토큰 받기 url에 Post 형태로 넘겨주어야 하는데,

여러 정보를 넘겨주는데 속도가 느려 Buffer(버퍼)로 데이터를 한꺼번에 처리하여 속도를 빠르게 처리하도록 해주었다.

BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
bw.write(sendMessage);
bw.flush();
bw.close();

▶ HttpURLConnection 객체는 Post 방식으로 데이터를 넘겨줄 것을 요청할때 OutputStream로 넘겨주는데,

     conn.setDoOutput(true);  // OutputStream으로 POST 데이터를 넘겨주겠다는 옵션.

    보낼 데이터는 문자열 형태임으로 기본 OutputStream을 문자열로 처리하는 OutputStreamWriter 이용하여 변환 후,

    처리 속도를 높이기위해 버퍼 문자열 형태인 BufferWriter 을 이용하여 보낸준 것이다. 

    해당 데이터를 버퍼를 이용해 넘겨주었으면 버퍼의 부하를 대비해 초기화(flush)를 해주어야한다.

 

BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "", result = "";
while ((line = br.readLine()) != null) {
		result += line;
}
br.close();

▶ HttpURLConnection 객체는 데이터를 가져올 때 기본 InputStream로 가져오는데, 가져온 형태도 빠른 처리 속도를 위해 버퍼 문자열로 변환해주며, 요청한 데이터 값을 한줄씩 읽어온다. (가져온 데이터는 버퍼에 저장되는게 아니기 때문에 초기화는 안해도 된다.)

 

JsonElement element = JsonParser.parseString(result);
accessToken = element.getAsJsonObject().get("access_token").getAsString();

▶ 응답 받는 데이터들은 {"키" : 값, "키" : 값 } 형태로 받기 때문에, 받아온 값중에서 토큰 값(access_token)만 가져와 변수 설정해준다.(토큰이 있어야 유저 정보를 가져올 수 있다.)

(사용자 정보 가져오는 방법 자세히보기 -  getUserInfo메소드)

더보기

카카오 개발 홈페이지에서 [문서] > [카카오 로그인] > [Rest API] 에서 자세한 설정 방법들을 볼 수 있다.

'사용자 정보 가져오기' 에서 Host 로 작성된 정보와 페이지 처리 방식을 참고하여, url 은 아래 형태처럼 작성해주면 된다.

 

예제에서는 아래 홈페이지 설정방식을 보고 사용자 정보 가져오는 url 형태와 데이터를 가져오는 인증키를 이와 같이 변수로 설정해주었다.

(*사용자 정보 가져오기에서 필수 요청 헤더 값 토큰을 넘겨주는데 여기서 헤더란?) 
String reqURL = "https://kapi.kakao.com/v2/user/me";
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("POST");
// 요청에 필요한 Header에 포함될 내용
conn.setRequestProperty("Authorization", "Bearer " + accessToken);

 

처리 속도를 위해 가져온 데이터(InputStream)을 버퍼 문자열로 가져와 한 줄씩 변수에 저장해준다.

한줄씩 저장된 해당 변수를 서버에서 사용하거나 클라이언트측에 출력하려면 키/값 형태인 JSON과 Hash객체를 저장해주어야 한다.

(카카오 로그인 서비스 로그아웃 방법 자세히 보기 - logout메소드)

더보기

카카오 개발 홈페이지에서 [문서] > [카카오 로그인] > [Rest API] 에서 자세한 설정 방법들을 볼 수 있다.

'로그아웃' 에서 Host 로 작성된 정보와 페이지 처리 방식을 참고하여, url 은 아래 형태처럼 작성해주면 된다.

 

'Programming > Spring' 카테고리의 다른 글

[AWS] Amazon EC2 인스턴스를 이용해 파일 업로드(연결)해보기  (0) 2022.11.02
[Spring] 로그인 메일 인증번호 발송하기  (0) 2022.10.25
[Spring] 스프링을 시작하며...(2) Spring Legacy Project 세팅하기  (0) 2022.10.24
[Spring] 스프링을 시작하며...(1) 스프링 개발환경 세팅하기  (0) 2022.10.19
    'Programming/Spring' 카테고리의 다른 글
    • [AWS] Amazon EC2 인스턴스를 이용해 파일 업로드(연결)해보기
    • [Spring] 로그인 메일 인증번호 발송하기
    • [Spring] 스프링을 시작하며...(2) Spring Legacy Project 세팅하기
    • [Spring] 스프링을 시작하며...(1) 스프링 개발환경 세팅하기
    Criming
    Criming

    티스토리툴바