오늘은 부트캠프 71일차이다. 오늘은 오전에 Oauth를 이용하여 카카오 로그인 구현을 어떻게 하는지 찾아보고 코딩을 하였다. 예전에 공부한 자료로 만들어보았고, 하지만 문제 있었다. 처음 회원가입하는 것부터 로그인까지는 구현을 하였는데 로그인을 한 이후에는 404에러 떠서 새로고침을 하니 다시 되었다. 다행히 내일까지 오류를 고쳐야겠다.
Sevice 구현
public String kakaoLogin(String code, HttpServletResponse response) throws JsonProcessingException { // 1. "인가 코드"로 "액세스 토큰" 요청 String accessToken = getToken(code); // 2. 토큰으로 카카오 API 호출 : "액세스 토큰"으로 "카카오 사용자 정보" 가져오기 KakaoUserInfoDto kakaoUserInfo = getKakaoUserInfo(accessToken); // 3. 필요시에 회원가입 User kakaoUser = registerKakaoUserIfNeeded(kakaoUserInfo); // 4. JWT 토큰 반환 String createToken = jwtUtil.createToken(kakaoUser.getUserId(), kakaoUser.getRole()); // response.addHeader(JwtUtil.AUTHORIZATION_HEADER, createToken); return createToken; } // 1. "인가 코드"로 "액세스 토큰" 요청 private String getToken(String code) throws JsonProcessingException { // HTTP Header 생성 HttpHeaders headers = new HttpHeaders(); headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); // HTTP Body 생성 MultiValueMap<String, String> body = new LinkedMultiValueMap<>(); body.add("grant_type", "authorization_code"); body.add("client_id", "b8054d0d502a7f824aa2ca329d139607"); body.add("redirect_uri", "http://localhost:5500/index.html"); body.add("code", code); // HTTP 요청 보내기 HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(body, headers); RestTemplate rt = new RestTemplate(); ResponseEntity<String> response = rt.exchange( "https://kauth.kakao.com/oauth/token", HttpMethod.POST, kakaoTokenRequest, String.class ); // HTTP 응답 (JSON) -> 액세스 토큰 파싱 String responseBody = response.getBody(); ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(responseBody); return jsonNode.get("access_token").asText(); } // 2. 토큰으로 카카오 API 호출 : "액세스 토큰"으로 "카카오 사용자 정보" 가져오기 private KakaoUserInfoDto getKakaoUserInfo(String accessToken) throws JsonProcessingException { // HTTP Header 생성 HttpHeaders headers = new HttpHeaders(); headers.add("Authorization", "Bearer " + accessToken); headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8"); // HTTP 요청 보내기 HttpEntity<MultiValueMap<String, String>> kakaoUserInfoRequest = new HttpEntity<>(headers); RestTemplate rt = new RestTemplate(); ResponseEntity<String> response = rt.exchange( "https://kapi.kakao.com/v2/user/me", HttpMethod.POST, kakaoUserInfoRequest, String.class ); String responseBody = response.getBody(); ObjectMapper objectMapper = new ObjectMapper(); JsonNode jsonNode = objectMapper.readTree(responseBody); Long id = jsonNode.get("id").asLong(); String nickname = jsonNode.get("properties") .get("nickname").asText(); String email = jsonNode.get("kakao_account") .get("email").asText(); log.info("카카오 사용자 정보: " + id + ", " + nickname + ", " + email); return new KakaoUserInfoDto(id, nickname, email); } // 3. 필요시에 회원가입 private User registerKakaoUserIfNeeded(KakaoUserInfoDto kakaoUserInfo) { // DB 에 중복된 Kakao Id 가 있는지 확인 Long kakaoId = kakaoUserInfo.getId(); User kakaoUser = userRepository.findByKakaoId(kakaoId) .orElse(null); if (kakaoUser == null) { // 카카오 사용자 email 동일한 email 가진 회원이 있는지 확인 String kakaoEmail = kakaoUserInfo.getEmail(); User sameEmailUser = userRepository.findByEmail(kakaoEmail).orElse(null); if (sameEmailUser != null) { kakaoUser = sameEmailUser; // 기존 회원정보에 카카오 Id 추가 kakaoUser = kakaoUser.kakaoIdUpdate(kakaoId); } else { // 신규 회원가입 // password: random UUID String password = UUID.randomUUID().toString(); String encodedPassword = passwordEncoder.encode(password); // email: kakao email String email = kakaoUserInfo.getEmail(); kakaoUser = new User(kakaoUserInfo.getNicknmae(), kakaoId, encodedPassword, email, UserRole.USER); } userRepository.save(kakaoUser); } return kakaoUser; }