04.03 TIL
2023. 4. 3. 14:44ㆍ개발일지
카카오 소셜로그인 삽질 6일차....
카카오 맘편히 쉽겠다 생각하고 시작한게 문제의 시작
첫날에 localhost:8080에서 index파일로 테스트를 했을 때 성공해서 프론트 분들께 넘겼드렸으나, 로컬에서는 토큰을 받지만 프론트에서는 토큰을 못받으셨음 그래서 리다이렉트uri를 프론트서버 localhost:3000으로 맞춰드리고 했으나 토큰을 2번 요청으로 오류가 발생하지만 실행은 되었습니다. 그래서 팀원 회의를 통해 어느정도 기능구현과 CSS가 자리잡고 다시 해보기로 했습니다 그래서 어느 정도 구현이 완료되고 프론트 서버 배포 후 거기에 리다이렉트uri를 프론트 서버와 맞추자마자 500오류의 시작 여기서부터 삽질 시작...
우선 카카오 Service 로직
@Slf4j
@Service
@RequiredArgsConstructor
public class KakaoService {
private final PasswordEncoder passwordEncoder;
private final MemberRepository memberRepository;
private final RefreshTokenRepository refreshTokenRepository;
private final JwtUtil jwtUtil;
public ApiResponseDto<SuccessResponse> kakaoLogin(String code, HttpServletResponse response) throws JsonProcessingException {
log.info("로그인 service 진입");
// 1. "인가 코드"로 "액세스 토큰" 요청
String accessToken = getToken(code);
System.out.println("code = " + code);
log.info("인가코드 요청 완료");
System.out.println("accessToken = " + accessToken);
// 2. 토큰으로 카카오 API 호출 : "액세스 토큰"으로 "카카오 사용자 정보" 가져오기
SocialUserInfoDto userInfo = getKakaoUserInfo(accessToken);
log.info("accessToken 성공");
// 3. 필요시에 회원가입
Member member = registerKakaoUserIfNeeded(userInfo);
System.out.println("userInfo = " + userInfo);
System.out.println("accessToken = " + accessToken);
// 4. JWT 토큰 반환
TokenDto tokenDto = jwtUtil.createAllToken(member.getEmail());
// Member Email값으로 refreshToken을 찾는다
Optional<RefreshToken> refreshToken = refreshTokenRepository.findAllByMemberId(member.getEmail());
if(refreshToken.isPresent()) {
refreshTokenRepository.save(refreshToken.get().updateToken(tokenDto.getRefresh_Token()));
}else {
RefreshToken newToken = new RefreshToken(tokenDto.getRefresh_Token(), member.getEmail());
refreshTokenRepository.save(newToken);
}
System.out.println("accessToken = " + accessToken);
return ResponseUtils.ok(SuccessResponse.of(HttpStatus.OK,"로그인 성공"));
}
// 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");
log.info("grant_type 인증 성공");
//REST API KEY
body.add("client_id", "bdb9f0d03a95450cca094def1b12464f");
log.info("client_id 인증 성공");
body.add("redirect_uri", "https://fe-fawn.vercel.app/kakao/callback");
log.info("redirect_uri 인증 성공");
body.add("code", code);
log.info("code 인증 성공");
log.info("여기는 코드 " + code);
// HTTP 요청 보내기
HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(body, headers);
RestTemplate rt = new RestTemplate();
ResponseEntity<String> response = null;
log.info(response + "null");
System.out.println("response = " + response);
try {
System.out.println("try문 진입");
log.info("try문 안 진입입");
response = rt.exchange(
"https://kauth.kakao.com/oauth/token",
HttpMethod.POST,
kakaoTokenRequest,
String.class
);
} catch (HttpClientErrorException e) {
System.out.println("catch문 진입");
log.info("catch문 안 진입");
log.error("Kakao API authentication failed with status code " + e.getRawStatusCode());
log.info("getRawStatusCode 오류 패스");
log.error("Response headers: " + e.getResponseHeaders());
log.info("getResponseHeaders 오류 패스");
log.error("Response body: " + e.getResponseBodyAsString());
log.info("getResponseBodyAsString 오류 패스");
throw e;
}
// 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);
log.info("responseBody 입니다.");
System.out.println("responseBody = " + responseBody);
return jsonNode.get("access_token").asText();
}
// 2. 토큰으로 카카오 API 호출 : "액세스 토큰"으로 "카카오 사용자 정보" 가져오기
private SocialUserInfoDto 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 SocialUserInfoDto(id, nickname, email);
}
// 3. 필요시에 회원가입
private Member registerKakaoUserIfNeeded(SocialUserInfoDto userInfo) {
// 로그인 타입 && 사용자 EMAIL로 회원 유무 확인
Member findUser = memberRepository.findByEmail(userInfo.getEmail())
.orElse(null);
if(findUser == null){
findUser = memberRepository.save(Member.builder()
.nickname(userInfo.getNickname())
.password(passwordEncoder.encode(UUID.randomUUID().toString()))
.email(userInfo.getEmail())
.loginType(LoginType.KAKAO_USER)
.build());
}else {
findUser.updateLoginStatus(LoginType.KAKAO_USER);
}
return findUser;
}
}
그리고 Controller 로직
// 소셜로그인
@GetMapping("/kakao/callback")
public ApiResponseDto<SuccessResponse> kakaoLogin(@RequestParam String code, HttpServletResponse response)throws JsonProcessingException {
return kakaoService.kakaoLogin(code, response);
}
이렇게 짜고 프론트분들 로직도 보았으나 아무리 코드를 뒤집어 엎고 다시짜도 계속 오류...
이렇게 4일을 삽질을 하다가 허용IP를 추가하라는 글에 카카오 내 애플리케이션 -> 허용 IP주소 들어가보니.... 저번에 기능과 CSS잡기 전에 토큰 2번발급되는거 잡으려고 허용IP주소를 설정해놨던걸 잊고있었습니다.. 그래서 그걸 지우자마자 200.... 이렇게 허무할수가... 그래도 성공했으니 기분은 좋다 ㅎ
'개발일지' 카테고리의 다른 글
04.06 TIL (Nginx) (0) | 2023.04.07 |
---|---|
04.04 TIL (SSE) (0) | 2023.04.07 |
03.27 Redis 사용하는 이유 (0) | 2023.03.27 |
03.25 TIL (0) | 2023.03.25 |
03.24 이메일 인증(feat. 네이버,구글) (0) | 2023.03.24 |