[#35] KakaoOAuth 로그인

2025. 3. 18. 01:09·LG 유플러스 유레카 SW/Spring
목차
  1. 시퀀스
  2. 카카오 개발자 센터
  3. 구현

시퀀스

 

카카오 개발자 센터

https://developers.kakao.com/

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

카카오 로그인 기능 활성화 방법
1) 내 애플리케이션 > 제품 설정 > 카카오 로그인
- 활성화 설정: ON
- Redirect URI: http://localhost:8080/kakaoLoginCallback
- 동의 항목: account_email (개인 개발자 비즈 앱 전환이 되어야 동의항목으로 설정할 수 있음)

2) 내 애플리케이션 > 앱 설정 > 앱 키
- REST API 키 복사

 

구현

Frontend 설정

  • 적당한 image icon 가져오기

  • 적당한 위치에 icon 보이기(index.html)
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <span id="loginSpan">
      <a href="http://localhost:8080/kakaoLogin">
        <img src="img/kakao.png" alt="" />
      </a>
    </span>
  </body>
  <script src="js/index.js"></script>
</html>

 

Backend 설정

  • 개발자 키 secu.properties에 등록
DB_DRIVER=com.mysql.cj.jdbc.Driver
DB_URL=jdbc:mysql://localhost:3306/ureca
DB_USER=ureca
DB_PW=ureca

KAKAO_API_KEY=XXX...
  • application.properties에서 secu.properties의 KEY를 읽어 오도록 설정
kakao.api.key=${KAKAO_API_KEY}
  • KakaoOAuthController.java에서 kakao 인증 화면으로 redirect한 후 사용자 동의 코드 받기
@Controller
public class KakaoOAuthController {

	@Value("${kakao.api.key}")
	String KAKAO_API_KEY ;

	@GetMapping("kakaoLogin")
	public String kakaoLogin() {
		
		return "redirect:https://kauth.kakao.com/oauth/authorize?client_id=" 
		+ KAKAO_API_KEY 
				+ "&redirect_uri=http://localhost:8080/kakaoLoginCallback&response_type=code";
	}
	
	@GetMapping("kakaoLoginCallback")
	public String kakaoCallback(@RequestParam String code){
	  System.out.println("사용자 동의 코드:" + code);
		return null;
	}
}
  • KakaoOAuthService.java에서 kakao에게 동의 코드 내밀며 AccessToken 요청하기
@Service
public class KakaoOAuthService {
    @Value("${kakao.api.key}")
	String KAKAO_API_KEY ;
	public String getKakaoAccessToken(String code) throws Exception {
		String reqURL = "https://kauth.kakao.com/oauth/token";

		URL url = new URL(reqURL);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();

		// POST 요청을 위해 기본값이 false인 setDoOutput을 true로 설정
		conn.setRequestMethod("POST");
		conn.setDoOutput(true); // 응답 내용을 stream 형태로 직접 가공해서 꺼낸다는 의미

		// POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
		BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
		StringBuilder sb = new StringBuilder();
		sb.append("grant_type=authorization_code");
		sb.append("&client_id=" + KAKAO_API_KEY);
		sb.append("&redirect_uri=http://localhost:8080/kakaoLoginCallback");
		sb.append("&code=" + code);
		bw.write(sb.toString());
		bw.flush(); // 버퍼가 다 안채워져도 전송

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

		// 요청을 통해 얻은 JSON 타입의 Response 메세지 읽어오기
		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);

		// Jackson 라이브러리로 JSON 파싱
		ObjectMapper objectMapper = new ObjectMapper(); // JSON을 다루는 클래스
		JsonNode jsonNode = objectMapper.readTree(result); // JSON 문자열을 JsonNode 객체로 변환하여 트리 구조로 JSON 데이터 다룰 수 있게 함

		String accessToken = jsonNode.get("access_token").asText();
		String refreshToken = jsonNode.get("refresh_token").asText();

		System.out.println("accessToken : " + accessToken);
		System.out.println("refreshToken : " + refreshToken);

		br.close();
		bw.close();

		return accessToken;
	}
}
  • KakaoOAuthController.java에서 AccessToken 출력해보기
@Controller
public class KakaoOAuthController {

	@Value("${kakao.api.key}")
	String KAKAO_API_KEY ;

	@GetMapping("kakaoLogin")
	public String kakaoLogin() {
		
		return "redirect:https://kauth.kakao.com/oauth/authorize?client_id=" 
		+ KAKAO_API_KEY 
				+ "&redirect_uri=http://localhost:8080/kakaoLoginCallback&response_type=code";
	}
	
	@GetMapping("kakaoLoginCallback")
	public String kakaoCallback(@RequestParam String code){
	  System.out.println("사용자 동의 코드:" + code);
	  String access_Token = oAuthService.getKaKaoAccessToken(code);
	  System.out.println("access_Token :" + access_Token );
		return null;
	}
}
  • KakaoOAuthService.java에서 kakao에게 AccessToken 내밀며 email 요청하기
@Service
public class KakaoOAuthService {

	// ... 생략

	public String getEmail(String accessToken) throws Exception {
		String reqURL = "https://kapi.kakao.com/v2/user/me";

		// access_token을 이용하여 사용자 정보 조회
		URL url = new URL(reqURL);
		HttpURLConnection conn = (HttpURLConnection) url.openConnection();

		conn.setRequestMethod("POST");
		conn.setDoOutput(true);
		conn.setRequestProperty("Authorization", "Bearer " + accessToken);

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

		// 요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
		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);

		// Jackson 라이브러리로 JSON 파싱
		ObjectMapper objectMapper = new ObjectMapper();
		JsonNode jsonNode = objectMapper.readTree(result);

		boolean hasEmail = jsonNode.get("kakao_account").get("has_email").asBoolean();
		String email = "";
		if (hasEmail) {
			email = jsonNode.get("kakao_account").get("email").asText();
		}

		System.out.println("email : " + email);

		br.close();

		return email;

	}
}
  • KakaoOAuthController.java에서 email과 AccessToken을 쿠키로 설정해서 kakao 서버로 리턴하면 kakao에서 클라이언트로 redirect page를 보내준다. 이때 클라이언트 브라우저에 쿠키가 저장
@Controller
public class KakaoOAuthController {

	@Value("${kakao.api.key}")
	String KAKAO_API_KEY ;

	@GetMapping("kakaoLogin")
	public String kakaoLogin() {
		
		return "redirect:https://kauth.kakao.com/oauth/authorize?client_id=" 
		+ KAKAO_API_KEY 
				+ "&redirect_uri=http://localhost:8080/kakaoLoginCallback&response_type=code";
	}
	
	@GetMapping("kakaoLoginCallback")
	public String kakaoCallback(@RequestParam String code, HttpServletRequest request, HttpServletResponse response){
	  System.out.println("사용자 동의 코드:" + code);
	  String access_Token = oAuthService.getKaKaoAccessToken(code);
	  System.out.println("access_Token :" + access_Token );
	  String email = oAuthService.getKakaoUser(access_Token);
	  System.out.println("email  :" + email  );
	  
		if (email != null) {
			// db에 저장
			oAuthService.insertLoginInfo(email, access_Token);
			
			Cookie c1 = new Cookie("email", email);
			Cookie c2 = new Cookie("Authorization", access_Token);
			
			response.addCookie(c1);
			response.addCookie(c2);

		}

		return "redirect:http://localhost:5500/";
	}
}

 

Frontend 설정

  • KakaoOAuth 로그인 마지막에 준 redirect page가 index.html이고 여기서 member.js를 링크 걸고 있으므로 member.js 로딩 시에 쿠키에 있는 정보를 가져와서 적절히 처리
// 로그아웃
document
  .getElementById("loginSpan")
  .addEventListener("click", async (event) => {
    // 쿠키 삭제
    removeCookie("Authorization");
    removeCookie("email");

    window.location.reload();
  });

// 유틸리티
function getCookie(cname) {
  let name = cname + "=";
  let decodedCookie = decodeURIComponent(document.cookie);
  let ca = decodedCookie.split(";");
  for (let i = 0; i < ca.length; i++) {
    let c = ca[i];
    while (c.charAt(0) == " ") {
      c = c.substring(1);
    }
    if (c.indexOf(name) == 0) {
      return c.substring(name.length, c.length);
    }
  }
  return "";
}

function removeCookie(cname) {
  document.cookie = cname + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;";
}

Authorization = getCookie("Authorization");
email = getCookie("email");
if (Authorization && email) {
  //   axios.defaults.headers.common["Authorization"] = Authorization; // Authorization 헤더 설정
  document.getElementById("loginSpan").innerHTML = `${email}  
    <button class="btn btn-danger btn-sm" id="logoutBtn">Logout</button>`;
}
728x90
반응형

'LG 유플러스 유레카 SW > Spring' 카테고리의 다른 글

[#33] RESTful 방식 + Swagger 사용  (0) 2025.03.14
[#31] 토큰 인증 방식  (0) 2025.03.11
[#30] XSS/Tabnabbing 공격  (0) 2025.03.10
[#29] 쇼핑몰 연동 실습 - SQL Injection + Connection Pool  (1) 2025.03.07
[#28] 쇼핑몰 연동 실습 - 다중 서버 세션 문제 해결 + 사용자 인증  (1) 2025.03.06
  1. 시퀀스
  2. 카카오 개발자 센터
  3. 구현
'LG 유플러스 유레카 SW/Spring' 카테고리의 다른 글
  • [#33] RESTful 방식 + Swagger 사용
  • [#31] 토큰 인증 방식
  • [#30] XSS/Tabnabbing 공격
  • [#29] 쇼핑몰 연동 실습 - SQL Injection + Connection Pool
nueos
nueos
  • nueos
    nueos 공부 기록
    nueos
  • 전체
    오늘
    어제
    • 분류 전체보기 (191)
      • 해커톤 (1)
      • 네이버 BoostCamp (6)
      • LG 유플러스 유레카 SW (3)
        • React (21)
        • TypeScript (2)
        • JavaScript (2)
        • HTML+CSS (5)
        • Spring (7)
        • Java (6)
        • SQL (2)
        • Algorithm (8)
        • CX (6)
        • Git (2)
        • 프로젝트 (2)
        • 스터디 (9)
        • 과제 (8)
        • 특강 (1)
      • React (3)
      • Next (0)
      • Javascript (2)
      • HTML (2)
      • CSS (9)
      • Algorithm (6)
      • Database (0)
      • OS (13)
      • C++ (24)
      • Python (1)
      • jQuery (1)
      • Django (1)
      • Git (1)
      • 개발 지식 (3)
      • 정보 보안 (22)
      • 포렌식 (1)
      • 암호 (2)
      • 기타 (4)
      • 패스트캠퍼스 FE 프로젝트십 (5)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    힙
    Queue
    스택
    exhaustive search
    디지랩챌린지
    제주지역혁신플랫폼지능형서비스사업단
    기술로바꾸는세상
    제주해커톤
    heap
    완전 탐색
    디지털혁신
    Stack
    큐
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.2
nueos
[#35] KakaoOAuth 로그인
상단으로

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.