나와바리 - 카카오 API 로그인, 로그아웃

Sungmin·2023년 3월 31일
0

카카오 로그인 동작 흐름

1번부터 5번까지는 프론트에서 수행하면 되는 작업이다.

그러나 혼자 만들어보는 과정도 중요하기 때문에 1번부터 9번까지의 과정을 수행하였다.


https://developers.kakao.com/docs/latest/ko/kakaologin/common

먼저 카카오디벨로퍼에 접속한다

REST API키가 중요하다.

카카오 로그인 상태를 활성화 해 주고
Redirect URI는 코드를 발급받는 페이지 설정인데 localhost:8080/login으로 해주었다

동의항목은 이렇게 해 주었다.


로그인 할 페이지 주소이다.
접속하면 이렇게 뜨는것을 볼 수 있다.

kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code


Gson 추가

build.gradle

	implementation 'com.google.code.gson:gson:2.10.1'

Controller

@RestController
@RequiredArgsConstructor
public class MemberController {

    private final MemberService memberService;

    /**
     * 카카오 로그인
     */
    @GetMapping("/login")
    public void login(@RequestParam String code) {
        String access_Token = memberService.getKakaoAccessToken(code);
        System.out.println("code = " + code);
        HashMap<String, Object> userInfo = memberService.getUserInfo(access_Token);
        System.out.println("userInfo = " + userInfo);
    }

    /**
     * 카카오 로그아웃
     */
    @PostMapping("/logout")
    public void logout(HttpSession session) {
        memberService.kakaoLogout((String)session.getAttribute("access_Token"));
        session.removeAttribute("access_Token");
        session.removeAttribute("userId");
    }

}

Service

@Slf4j
@Service
@RequiredArgsConstructor
public class MemberService {

    public String getKakaoAccessToken (String code) {
        String access_Token = "";
        String refresh_Token = "";
        String reqURL = "https://kauth.kakao.com/oauth/token";

        try {
            URL url = new URL(reqURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            //POST 요청을 위해 기본값이 false인 setDoOutput을 true로
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);

            //POST 요청에 필요로 요구하는 파라미터 스트림을 통해 전송
            BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
            StringBuilder sb = new StringBuilder();
            sb.append("grant_type=authorization_code");
            sb.append("&client_id=27eb3015ee913717948781cb023560f3"); // TODO REST_API_KEY 입력
            sb.append("&redirect_uri=http://localhost:8080/login"); // TODO 인가코드 받은 redirect_uri 입력
            sb.append("&code=" + code);
            bw.write(sb.toString());
            bw.flush();

            //결과 코드가 200이라면 성공
            int responseCode = conn.getResponseCode();
            System.out.println("responseCode : " + responseCode);

            //요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = "";
            String result = "";

            while ((line = br.readLine()) != null) {
                result += line;
            }
            System.out.println("response body : " + result);

            //Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성
            Gson gson = new Gson();

            JsonElement element = gson.fromJson(result, JsonElement.class);

            access_Token = element.getAsJsonObject().get("access_token").getAsString();
            refresh_Token = element.getAsJsonObject().get("refresh_token").getAsString();

            System.out.println("access_token : " + access_Token);
            System.out.println("refresh_token : " + refresh_Token);

            br.close();
            bw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return access_Token;
    }
    public HashMap<String, Object> getUserInfo (String access_Token) {

        //    요청하는 클라이언트마다 가진 정보가 다를 수 있기에 HashMap타입으로 선언
        HashMap<String, Object> userInfo = new HashMap<>();
        String reqURL = "https://kapi.kakao.com/v2/user/me";
        try {
            URL url = new URL(reqURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");

            //    요청에 필요한 Header에 포함될 내용
            conn.setRequestProperty("Authorization", "Bearer " + access_Token);

            int responseCode = conn.getResponseCode();
            System.out.println("responseCode : " + responseCode);

            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            String line = "";
            String result = "";

            while ((line = br.readLine()) != null) {
                result += line;
            }
            System.out.println("response body : " + result);

            Gson gson = new Gson();
            JsonElement element = gson.fromJson(result, JsonElement.class);

            JsonObject properties = element.getAsJsonObject().get("properties").getAsJsonObject();
            JsonObject kakao_account = element.getAsJsonObject().get("kakao_account").getAsJsonObject();
            String kakao_id = element.getAsJsonObject().get("id").getAsString();

            String nickname = properties.has("nickname") ? properties.get("nickname").getAsString() : null;
            String profileImage = properties.has("profile_image") ? properties.get("profile_image").getAsString() : null;
            String age = kakao_account.has("age_range") ? kakao_account.get("age_range").getAsString() : null;
            String gender = kakao_account.has("gender") ? kakao_account.get("gender").getAsString() : null;

            userInfo.put("kakao_id", kakao_id);
            userInfo.put("nickname", nickname);
            userInfo.put("profile_image", profileImage);
            userInfo.put("age_range", age);
            userInfo.put("gender", gender);

        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return userInfo;
    }


    public void kakaoLogout(String access_Token) {
        String reqURL = "https://kapi.kakao.com/v1/user/logout";
        try {
            URL url = new URL(reqURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Authorization", "Bearer " + access_Token);

            int responseCode = conn.getResponseCode();
            System.out.println("responseCode : " + responseCode);

            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));

            String result = "";
            String line = "";

            while ((line = br.readLine()) != null) {
                result += line;
            }
            System.out.println(result);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

정상적으로 code, access_token, refresh_token 그리고 회원정보가 출력되는것은 볼 수 있다.

추후

code부분은 클라이언트 개발자가 처리하여 access_token을 넘겨줄 것이다.
백엔드에서 access_token을 받으면 그 값을 이용해 사용자 정보를 받아 올 수 있다.

처음 시도해보는 카카오 로그인 API 구현이었는데 처음엔 어렵게만 생각했던 과정을 겪고나니 생각보다 간단했다.
Service부분의 코드는 이렇게 나눠져 있다.

  1. connection 생성
  2. POST로 보낼 Body 작성
  3. 받아온 결과 JSON파싱(Gson)
  4. 파싱한 객체를 element에 넣고
  5. element에서 getAsJsonObject().get("properties").getAsJsonObject(); 로 닉네임과 프로필이미지를 담은 properties를 가져와 properties변수에 넣음
    마찬가지로 나이대와 성별을 담은 "kakao_account"를 가져와 kakao_account에 넣음. 아이디는 Stirng 형태이므로 getAsString();으로 가져옴
  6. 각각의 가져올 값이 있는지 여부를 검사하기 위해 has메서드를 사용했고 get메서드는 일치하는 값을 반환. 만약 값이 null이라면 이를 처리하기 위해 삼항 연산자를 이용하여 null인 경우 null을 넣도록 함
  7. userInfo에 put하여 넣어줌

이 코드를 참고하여 다른 API통신도 시도해 볼 예정이다.

참고: https://antdev.tistory.com/36?category=807235

profile
Let's Coding

0개의 댓글