4차산업혁명의 일꾼/Java&Spring웹개발과 서버 컴퓨터

카카오 로그인 OAuth 기능 구현

르무엘 2022. 7. 19. 14:36

카카오 로그인 구현 요청은 위와 같다.

 

자 인증코드 받은것으로 토큰이 전달되면 

그것으로 API를 호출하는 것이다.

 

토큰이 유효한지 확인하여 유효하면 로그인이 되는 것이다.

 

카카오 디벨로버 사이트에서

해당 웹사이트를 등록할수 있다.

Kakao Developers 내 애플리케이션

 

카카오계정 로그인

여기를 눌러 링크를 확인하세요.

accounts.kakao.com

 

어플리케이션 등록한후 앱설정의 플랫폼에 가서

웹플랫폼을 등록한다.

 

그리고 나서 로그인후 인가토큰을 받게될 Redirect URI(callback) 을 설정한다.

 

 

인가코드 요청은 html에서 하기와 같이 할수 있다.

'

본인의 발급받은 REST_API_KEY와  지정한 REDIRECT_URI를 입력한다.

발급받은 REST_API_KEY는 

하기 카카오계정에서 확인가능하다.

카카오계정 (kakao.com)

 

카카오계정 로그인

여기를 눌러 링크를 확인하세요.

accounts.kakao.com

 

 

카카오 로그인은 하기와 같이 된다.

순서대로 따라가면

인가코드로 엑세스토큰을 요청한다.

 

헤더랑 바디 설정을 해서 보내서 accessToken 을 Text로 받아온다.

private String getAccessToken(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", " ");
    body.add("redirect_uri", "http://localhost:8080/user/kakao/callback");
    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();
}

그 accessToken을 가지고

Http헤더의 Bearer에 넣고 요청을 보낸다.

 

그리고 id, nickename, email을 뽑아온다.

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();
    System.out.println("카카오 사용자 정보: " + id + ", " + nickname + ", " + email);
    return new KakaoUserInfoDto(id, nickname, email);
}

 

뽑아온 id,nickname,email 가

DB에 있는지 확인하고 없으면 등록한다.

private Users registerKakaoUserIfNeeded(KakaoUserInfoDto kakaoUserInfo) {
    // DB 에 중복된 Kakao Id 가 있는지 확인
    Long kakaoId = kakaoUserInfo.getId();
    Users kakaoUser = userRepository.findByKakaoId(kakaoId)
            .orElse(null);
    if (kakaoUser == null) {
        String kakaoEmail = kakaoUserInfo.getEmail();
        Users sameEmailUser = userRepository.findByEmail(kakaoEmail).orElse(null);

        if(sameEmailUser != null){
            kakaoUser = sameEmailUser;
            // 기존 회원 정보에 카카오 ID 추가
            kakaoUser.setKakaoId(kakaoId);
        }else{
            //신규회원 가입
            // user name 카카오 닉네임
            String nickname = kakaoUserInfo.getNickname();

            // password : random UUID
            String password = UUID.randomUUID().toString();
            String encodedPassword = passwordEncoder.encode(password);

            // email : kakao email
            String email = kakaoUserInfo.getEmail();
            // role : 일반 사용자
            UserRoleEnum role = UserRoleEnum.USER;

            kakaoUser = new Users(nickname, encodedPassword, email, role, kakaoId);

        }

        userRepository.save(kakaoUser);

    }
    return kakaoUser;
}

그리고 나서 자동(강제) 로그인을 하는것이다.

 

private void forceLogin(Users kakaoUser) {
    UserDetails userDetails = new UserDetailsImpl(kakaoUser);
    Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
    SecurityContextHolder.getContext().setAuthentication(authentication);
}

스프링 JPA를 활용해서 

스프링 프레임워크가 인증해버리고 들어가는것이다.ㅎㅎ

 

그림으로 보면 하기와 같다

로그인 성공시 하기와 같이 된다.

이상 스프링 카카오 로그인 OAuth 설명을 마친다.

LIST