Develop/Spring

[Spring] 스프링부트와 카카오 로그인연동하기(2)

지식작문 2024. 6. 16.

 

[Spring] 인텔리제이를 사용하는 스프링부트에 OAuth 2.0 기반 방식으로 카카오 로그인을 연동하기

 

< 토큰 받기>

 

POST 방식으로 토큰을 요청해야하는데, 주소는 위와 같다. 필수적인 5가지 데이터를 body로 응답 받아야 하기때문에, 키값방식으로 작성해주어야 한다. 표를 보면 [code=] 1편에서 받은 인가코드 값을 넣어주어야 한다.

import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

@Controller
public class UserController {

    @GetMapping("/login1")
    public String kakaologin() {
        return "login1"; // login1.mustache 파일 반환
    }

    @GetMapping("/login")
    public @ResponseBody String kakaoCallback(String code) {
        // POST 방식으로 key=value 데이터를 요청 (카카오쪽으로)

        RestTemplate rt = new RestTemplate();
        // HTTP 요청을 편하게 받는 라이브러리

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
        // header를 담는데이터

        // body는 보통 key, value의 쌍으로 이루어지기 때문에 자바에서 제공해주는 MultiValueMap 타입을 사용한다.
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "authorization_code");
        params.add("client_id", "");
        params.add("redirect_uri", "http://localhost:8080/login");
        params.add("code", code);
        // body를 담는 데이터

        HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(params, headers);
        // kakaoTokenRequest는 HTTPBody와 HTTPHeader를 하나의 데이터에 담는다.

        // POST 방식으로 HTTP 요청하고, 변수에 response(응답) 받는다.
        ResponseEntity<String> response = rt.exchange(
                "https://kauth.kakao.com/oauth/token", // https://{요청할 서버 주소}
                HttpMethod.POST, // 요청할 방식
                kakaoTokenRequest, // 요청할 때 보낼 데이터(header와 body가 합쳐짐)
                String.class // 요청 시 string타입으로 응답받음
        );
        return "카카오 토큰 요청 완료 : 토큰 요청에 대한 응답 : " + response;
    }
}
 

parms.add("client_id", "본인 REST API값")을 넣어주어야 한다.

서버를 재실행하고 페이지에 들어가서 로그인 하면 토큰 값이 뜬다. 값들이 정렬이나 줄바꿈이 안되어 있기 때문에 값들을 복사한다.

 

http://json.parser.online.fr/

 

JSON값을 정렬해서 보여주는 사이트로, 들어가서 붙여넣기를 해주면 JSON 값을 깔끔하게 볼 수 있다.

 

<엑세스 토큰 데이터를 자바오브젝트로 변환하기>

import lombok.Data;

@Data // getter,setter 작성 어노테이션
public class OAuthToken {
    private String access_token;
    private String token_type;
    private String refresh_token;
    private int expires_in;
    private String scope;
    private int refresh_token_expires_in;
}
 

[new][class]로 [OAuthToken]클래스를 만들어주자. JSON 데이터를 담기위한 객체를 만든것이다.

@Data 어노테이션을 작성한 것은 @getter와 @setter 어노테이션을 작성하지않고 사용하기 위해서다.

import com.example.TestProject.dto.OAuthToken;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

@Controller
public class UserController {

    @GetMapping("/login1")
    public String kakaologin() {
        return "login1"; // login1.mustache 파일 반환
    }

    @GetMapping("/login")
    public @ResponseBody String kakaoCallback(String code) {
        // POST 방식으로 key=value 데이터를 요청 (카카오쪽으로)

        RestTemplate rt = new RestTemplate();
        // HTTP 요청을 편하게 받는 라이브러리

        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
        // header를 담는데이터

        // body는 보통 key, value의 쌍으로 이루어지기 때문에 자바에서 제공해주는 MultiValueMap 타입을 사용한다.
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "authorization_code");
        params.add("client_id", "4a9c14d14d8eca3c3bbc1de3a27927c0");
        params.add("redirect_uri", "http://localhost:8080/login");
        params.add("code", code);
        // body를 담는 데이터

        HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest = new HttpEntity<>(params, headers);
        // kakaoTokenRequest는 HTTPBody와 HTTPHeader를 하나의 데이터에 담는다.

        // POST 방식으로 HTTP 요청하고, 변수에 response(응답) 받는다.
        ResponseEntity<String> response = rt.exchange(
                "https://kauth.kakao.com/oauth/token", // https://{요청할 서버 주소}
                HttpMethod.POST, // 요청할 방식
                kakaoTokenRequest, // 요청할 때 보낼 데이터(header와 body가 합쳐짐)
                String.class // 요청 시 string타입으로 응답받음
        );
        ObjectMapper objectMapper = new ObjectMapper();
        //JSON 데이터를 담기위한 object라이브러리 사용
        OAuthToken oauthToken = null;
        try{
            oauthToken = objectMapper.readValue(response.getBody(), OAuthToken.class);
        }catch(JsonMappingException e){
            e.printStackTrace();
        }catch(JsonProcessingException e){
            e.printStackTrace();
        }
        System.out.println("카카오엑세스토큰: "+oauthToken.getAccess_token()); //로그에 엑세스토큰 기록하기
        return response.getBody();
    }
}
 

JSON데이터를 담기위한 라이브러리를 만들기위해 [UserController]에서 다음과 같이 코드를 작성하고 서버를 실행 후 웹에 접속하면 카카오 액세스토큰에 대한 정보가 실행창에 출력될 것이다.

try코드를 작성하여 예외 처리를 해주었고, Data어노테이션을 사용했기때문에 get메서드를 사용할 수 있다.

<토큰을 통한 사용자 정보 조회>

 

 
 System.out.println("카카오엑세스토큰: "+oauthToken.getAccess_token()); //로그에 엑세스토큰 기록하기

        RestTemplate rt2 = new RestTemplate();
        // HTTP 요청을 편하게 받는 라이브러리

        HttpHeaders headers2 = new HttpHeaders(); //위랑 구별하기 위해 headers2로 변경
        headers2.add("Authorization", "Bearer "+oauthToken.getAccess_token()); //헤더 엑세스토큰으로 인증요청
        headers2.add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
        // header를 담는데이터

        HttpEntity<MultiValueMap<String, String>> kakaoProfileRequest2 = new HttpEntity<>(headers2);
        // kakaoProfileRequest2는 HTTPBody와 HTTPHeader를 하나의 데이터에 담는다.

        // POST 방식으로 HTTP 요청하고, 변수에 response(응답) 받는다.
        ResponseEntity<String> response2 = rt2.exchange(
                "https://kapi.kakao.com/v2/user/me", // https://{요청할 서버 주소}
                HttpMethod.POST, // 요청할 방식
                kakaoProfileRequest2, // 요청할 때 보낼 데이터(header와 body가 합쳐짐)
                String.class // 요청 시 string타입으로 응답받음
        );
  System.out.println(response2.getBody());
        return response2.getBody();
    }
 
 

요청을 받기위해서 위에서 사용한 코드를 복사해 엑세스토큰 기록하기에 붙여넣는다.

header에 인증방식 요청을 작성하고, body는 필요없기 때문에 삭제한다. 위 코드랑 구별하기 위해 변수를 약간씩 변경한다.

서버를 재실행 후 웹에 접속해 로그인을 하면 본인의 동의에 따른 정보가 나타나면서 로그인에 성공한다.

 

참고 : https://www.youtube.com/watch?v=NwQ_55l0Za4

 

댓글