진행중인 프로젝트에서 로그인 기능을 구현해야 하는데, 소셜 로그인을 사용하기로 했다.
그래서 OAuth 2.0을 사용해서 카카오를 통해 사용자 정보를 취득하기로 했다.
과정은 생략하겠다.
추가한 애플리케이션을 들어가 '요약 정보' 로 들어가면 REST API키가 있다.
우리는 이 REST API를 사용할 예정이다.
카카오 인증 서버에 API를 요청하고 Redirect URI를 통해 code값을 반환받기 때문에
Redirect URI를 설정해준다.
어떤 사용자 정보를 받을 지 동의 항목에서 설정을 한다.
kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code
REST_API_KEY는 아까전에 얻은 REST KEY 키를 기입하고,
REDIRECT_URI는 code를 반환할 URI를 기입하면 된다.
나중에 이 인가코드를 통해 카카오에게서 토큰을 받을 수 있다.
@ResponseBody
@GetMapping("/api/oauth/kakao")
public void kakaoCalllback(@RequestParam String code) {
log.info("code : " + code);
dependencies {
implementation 'com.google.code.gson:gson:2.8.7'
}
public String getKakaoAccessToken(String code) {
String accessToken = "";
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={code}");
sb.append("&redirect_uri=http://localhost:8080/api/oauth/kakao");
sb.append("&code=" + code);
bw.write(sb.toString());
bw.flush();
// 결과 코드가 200이라면 성공
int responseCode = conn.getResponseCode();
log.info("responseCode : " + responseCode);
// 요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
String result = getRequestResult(conn);
// Gson 라이브러리에 포함된 클래스로 JSON파싱 객체 생성
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
accessToken = element.getAsJsonObject().get("access_token").getAsString();
log.info("access_token : " + accessToken);
bw.close();
} catch (IOException e) {
e.printStackTrace();
}
return accessToken;
}
사용자 정보를 조회하면 되기 때문에 access token만 가져온다.
code를 통해 얻은 access token으로 사용자 정보를 조회한다.
public KakaoUserInfo getKakaoUserInfo(String token) {
String reqURL = "https://kapi.kakao.com/v2/user/me";
KakaoUserInfo kakaoUserInfo = new KakaoUserInfo();
//access_token을 이용하여 사용자 정보 조회
try {
URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoOutput(true);
conn.setRequestProperty("Authorization", "Bearer " + token); //전송할 header 작성, access_token전송
//결과 코드가 200이라면 성공
int responseCode = conn.getResponseCode();
log.info("responseCode : " + responseCode);
//요청을 통해 얻은 JSON타입의 Response 메세지 읽어오기
String result = getRequestResult(conn);
//Gson 라이브러리로 JSON파싱
JsonParser parser = new JsonParser();
JsonElement element = parser.parse(result);
JsonElement kakaoAccount = element.getAsJsonObject().get("kakao_account");
JsonElement profile = kakaoAccount.getAsJsonObject().get("profile");
//dto에 저장하기
kakaoUserInfo.setId(element.getAsJsonObject().get("id").getAsLong());
// kakaoUserInfo.setNickname(profile.getAsJsonObject().get("nickname").getAsString());
kakaoUserInfo.setProfileImgUrl(profile.getAsJsonObject().get("profile_image_url").getAsString());
// kakaoUserInfo.setThumnailImgUrl(profile.getAsJsonObject().get("thumbnail_image_url").getAsString());
kakaoUserInfo.setHasBirthDay(kakaoAccount.getAsJsonObject().get("has_birthday").getAsBoolean());
kakaoUserInfo.setHasGender(kakaoAccount.getAsJsonObject().get("has_gender").getAsBoolean());
if (kakaoUserInfo.isHasBirthDay()) {
kakaoUserInfo.setBirthday(kakaoAccount.getAsJsonObject().get("birthday").getAsString());
}
if (kakaoUserInfo.isHasGender()) {
kakaoUserInfo.setGender(kakaoAccount.getAsJsonObject().get("gender").getAsString());
}
log.info(kakaoUserInfo.toString());
} catch (IOException e) {
e.printStackTrace();
}
return kakaoUserInfo;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class KakaoUserInfo {
private Long id;
// private String nickname;
private String profileImgUrl;
// private String thumnailImgUrl;
private String birthday;
private boolean hasBirthDay;
private String gender;
private boolean hasGender;
}
마무리 후 다시 요청해보면 다음과 같은 결과가 출력된다.