카카오 로그인 api(2)

김종조·2024년 5월 23일
post-thumbnail
  1. 토큰 받기
  2. 발급 받은 토큰으로 사용자 정보 가져오기

Controller

	@GetMapping("login")
	public String kakaoApiTest(@RequestParam("code") String code,
						HttpServletResponse resp,
						Model model,
						RedirectAttributes ra) {
		
//		System.out.println("code ======== " + code);
		
		// 토큰 발급
		String accessToken = service.getKakaoToken(code);
		
//		System.out.println("accessToken ========= " + accessToken);
		
		// 사용자 정보 받아오기
		// 안에는 kakaoId, memberNickname이 들어있음
		HashMap<String, Object> userInfo = service.getUserInfo(accessToken);
		
		// 카카오로 회원 가입 한 회원인지 확인하기 
		// 처음 카카오 로그인 하는 경우 회원가입 시켜주기
		String memberId = String.valueOf(userInfo.get("kakaoId")); 
		String memberNickname = String.valueOf(userInfo.get("memberNickname"));
		
		System.out.println(memberId);
		System.out.println("ID" + memberId);
		
		int result = memberService.findIdForKakao("ID" + memberId);
		
		// 이미 존재하는회원
		if(result > 0) {
			Member loginMember = memberService.login("ID" + memberId);
			
			model.addAttribute("loginMember", loginMember);
			
			model.addAttribute("message", "카카오 로그인 완료!");
			
			System.out.println("카카오 로그인 완료");
			
			ra.addFlashAttribute("message", loginMember.getMemberNickname() + "님 환영합니다.");
			
		}else { // 존재하지 않은 회원일 경우 회원가입 시켜줌
			Member signMember = Member.builder()
								.memberId("ID" + memberId)
								.memberEmail("kakaoEmail")
								.memberPw("PW" + memberId)
								.memberNickname(memberNickname)
								.memberTel("kakaoTel")
								.build();
			
			int result2 = memberService.signForKakao(signMember);
			
			
			if(result2 > 0) {
				model.addAttribute("message", "카카오 회원가입 완료!");
				
				model.addAttribute("loginMember", signMember);
				
				ra.addFlashAttribute("message", signMember.getMemberNickname() + "님의 회원가입을 완료했습니다. 환영합니다.");
				
				System.out.println("카카오 회원가입");
			}else {
				System.out.println("카카오 회원가입 안됨");
			}
			
			
								
			
		}
		
		
		
		return "redirect:/";


Service

인가코드를 매개변수로 하는 토큰 발급 메서드

	// 인가 코드를 주고 토큰 발급 받아서 반환
	public String getKakaoToken(String code) {
		
		// POST방식으로 key=value 데이터를 요청(카카오쪽으로)
		String accessToken = "";
		
		RestTemplate rt = new RestTemplate();
		
		// HttpHeader 오브젝트 생성
		HttpHeaders headers = new HttpHeaders();
		headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
		
		// HttpBody 오브젝트 생성
		MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
		params.add("grant_type", "authorization_code");
		params.add("client_id", kakaoApiKey);
		params.add("redirect_uri", kakaoApiUri);
		params.add("code", code);
		
		// HttpHeader와 HttpBody를 하나의 오브젝트에 담기
		HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = 
				new HttpEntity<>(params, headers);
		
		// Http 요청하기 - POST 방식으로 , response 변수의 응답 받음
		ResponseEntity<String> response = rt.exchange("https://kauth.kakao.com/oauth/token",
				HttpMethod.POST,
				kakaoTokenRequest,
				String.class);
		
//		System.out.println("카카오 토큰 요청 완료 : 토큰 요청에 대한 응답 : " + response);
		
		ObjectMapper obMapper = new ObjectMapper();
		OAuthToken oauthToken = null;
		
		try {
			oauthToken = obMapper.readValue(response.getBody(), OAuthToken.class);
		} catch (JsonMappingException e) {
			e.printStackTrace();
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		
		accessToken = oauthToken.getAccess_token();
//		System.out.println("카카오 액세스 토큰 : " + accessToken);
		
		return accessToken;
	}


발급 받은 토큰 번호로 사용자 정보 가져오는 메서드

// 토큰을 받아서 user의 정보를 반환
public HashMap<String, Object> getUserInfo(String accessToken) {
	
	HashMap<String, Object> userInfo = new HashMap<>();
	
	RestTemplate rt2 = new RestTemplate();
	
	// HttpHeader 오브젝트 생성
	HttpHeaders headers2 = new HttpHeaders();
	headers2.add("Authorization", "Bearer " + accessToken);
	headers2.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
	

	// HttpHeader와 HttpBody를 하나의 오브젝트에 담기
	HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest2 = 
			new HttpEntity<>(headers2);
	
	// Http 요청하기 - POST 방식으로 , response 변수의 응답 받음
	ResponseEntity<String> response2 = rt2.exchange(
			"https://kapi.kakao.com/v2/user/me",
			HttpMethod.POST,
			kakaoTokenRequest2,
			String.class);
	
	System.out.println("response2 ======= " + response2.getBody());
	
	ObjectMapper objectMapper2 = new ObjectMapper();
	KakaoProfile kakaoProfile = null;
	try {
		kakaoProfile = objectMapper2.readValue(response2.getBody(), KakaoProfile.class);
	}catch(JsonMappingException e) {
		e.printStackTrace();
	}catch(JsonProcessingException e) {
		e.printStackTrace();
	}
	
	System.out.println("카카오 아이디(번호) : " + kakaoProfile.getId());
	System.out.println("카카오 닉네임 : " + kakaoProfile.getProperties().getNickname());
	
	userInfo.put("kakaoId", kakaoProfile.getId());
	userInfo.put("memberNickname", kakaoProfile.getProperties().getNickname());

	return userInfo;
}



토큰을 발급 받으면서 마주한 문제들

koe320 에러

설명에서는 같은 인가 코드를 두번 이상 사용 혹은 만료된 인가코드를 사용한 경우라고 했는데, 구글링 해본 결과 요청변수가 제대로 들어가지 않았을때도 koe320 에러가 발생한다고 했다.

해결 방법
HttpBody 오브젝트를 생성할때 요청변수 오타를 수정했다.

오타 수정후 잘 됨...

profile
웹 개발 공부 기록

3개의 댓글

comment-user-thumbnail
2024년 6월 3일

구글 api도 성공 하셨나요?

1개의 답글