Spring Boot에서 RestTemplate을 통해 구글 Open API를 호출하여 사용자 정보 받기
*SNS 간편로그인 - 구글 API 사용 등록 방법 완료 후 진행(관련 글 참고)
*프로세스는 카카오와 네이버 모두 동일(OAuth 2.0 X)
*Swagger3 관련 소스 포함
*자세한 설명 생략
▷ application.properties 설정
#GOOGLE
google.client.id="GOOGLE에서 제공한 Client ID"
google.client.secret="GOOGLE에서 제공한 Client Secret"
google.redirect.uri="GOOGLE에 설정한 Redirect URI"
▷ google.html
*로그인 화면(간단히 버튼만 생성)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>구글 테스트 페이지</title>
</head>
<body>
<div align="center">
<h1>구글 로그인 테스트</h1><br><br>
<a th:href="
@{https://accounts.google.com/o/oauth2/v2/auth(
client_id=${clientId},
redirect_uri=${redirectUri},
response_type=${responseType},
scope=${scope}
)}">
<img src="/images/google_login_btn.png">
</a>
</div>
</body>
</html>
▷ CmmUtil.java
*공통 유틸리티
/**
* 공통 유틸리티
*/
public class CmmUtil {
/**
*
* Object to String
*
* @param Object
* @return String
* @throws JsonProcessingException
*/
public static String getObjStr(Object obj) throws JsonProcessingException {
return new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.writeValueAsString(obj);
}
}
▷ GoogleController.java
*로그인 화면 진입 Controller 생성
/**
* 구글 TEST Controller
*/
@Controller
@RequestMapping("test")
public class GoogleContrller {
@Value("${google.client.id}")
private String GOOGLE_CLIENT_ID;
@Value("${google.redirect.uri}")
private String GOOGLE_REDIRECT_URI;
@GetMapping("/google.do")
public String kakaoLogin(Model model){
model.addAttribute("clientId", GOOGLE_CLIENT_ID);
model.addAttribute("redirectUri", GOOGLE_REDIRECT_URI);
model.addAttribute("scope", "profile email");
model.addAttribute("responseType", "code");
return "google";
}
}
▷ LGN1002Controller.java
*Redirect Controller 생성
/**
* 구글 Login Controller
*/
@Slf4j
@RestController
@RequestMapping("swai")
@Tag(name = "LGN", description = "Login Controller")
public class LGN1002Controller {
@Autowired
private LGNService lgnService;
@GetMapping("/google/login.do")
@Operation(summary = "SWAI-LGN-1002", description = "[구글] 로그인(Redirect)")
public LGN1002ResVO lgn1002(@Parameter(description = "인가 코드") @RequestParam("code") String code) {
LGN1002ResVO resVO = new LGN1002ResVO();
try {
resVO = lgnService.getLGN1002(code);
log.info("[구글] 로그인 최종 응답");
log.info(CmmUtil.getObjStr(resVO));
} catch (Exception e) {
}
return resVO;
}
}
▷ LGN1002ResVO.java
*최종 응답 VO
/**
* [구글] 로그인 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "[구글] 로그인 응답 VO")
public class LGN1002ResVO extends CmmResVO {
/** 결과 값 */
@JsonProperty("result")
@Schema(description = "결과 값")
public LGN1002VO result;
@Getter
@Setter
@ToString
@Schema(description = "[구글] 로그인 응답 VO")
public static class LGN1002VO {
@JsonProperty("sub")
@Schema(description = "사용자의 고유 식별자. 모든 Google 계정에서 유일하며 재사용되지 않습니다.")
public String sub;
@JsonProperty("name")
@Schema(description = "사용자의 전체 이름 (표시 가능한 형식).")
public String name;
@JsonProperty("given_name")
@Schema(description = "사용자의 이름.")
public String givenName;
@JsonProperty("family_name")
@Schema(description = "사용자의 성.")
public String familyName;
@JsonProperty("picture")
@Schema(description = "사용자의 프로필 사진 URL.")
public String picture;
@JsonProperty("email")
@Schema(description = "사용자의 이메일 주소. 이 값은 유일하지 않을 수 있으며 시간이 지남에 따라 변경될 수 있습니다.")
public String email;
@JsonProperty("email_verified")
@Schema(description = "사용자의 이메일 주소가 확인되었는지 여부. true일 경우 이메일이 확인된 상태입니다.")
public boolean emailVerified;
@JsonProperty("locale")
@Schema(description = "사용자의 언어 및 국가 정보. BCP 47 언어 태그 형식으로 제공됩니다.")
public String locale;
}
}
▷ CmmResVO.java
*공통 응답
/**
* 공통 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "공통 응답 VO")
public class CmmResVO {
/** Result Code */
@JsonProperty("resultCode")
@Schema(description = "Result Code")
public String resultCode = "0000";
/** Result Msg */
@JsonProperty("resultMsg")
@Schema(description = "Result Msg")
public String resultMsg = "성공";
/** Set Result */
public CmmResVO setResCmmResult(String resultCode, String resultMsg) {
this.resultCode = resultCode;
this.resultMsg = resultMsg;
return this;
}
}
▷ LGNService.java
/**
* Login Service
*/
public interface LGNService {
/** [구글] 로그인 **/
public LGN1002ResVO getLGN1002(String code);
}
▷ LGNServiceImpl.java
/**
* Login ServiceImpl
*
*/
@Service
public class LGNServiceImpl implements LGNService {
@Autowired
private GoogleApiService googleApi;
/**
* [구글] 로그인
*/
@Override
public LGN1002ResVO getLGN1002(String code) {
LGN1002ResVO result = new LGN1002ResVO();
try {
/* [구글] 토큰 발급 */
GoogleOAuthTokenVO token = googleApi.getOAuthToken(code);
/* [구글] 사용자 정보 조회 */
GoogleUserInfoVO userInfo = googleApi.getUserInfo(token.getAccess_token());
/* 사용자 정보 저장 */
/* 응답 값 설정 */
LGN1002VO vo = new LGN1002VO();
vo.setSub(userInfo.getSub());
vo.setName(userInfo.getName());
vo.setGivenName(userInfo.getGivenName());
vo.setFamilyName(userInfo.getFamilyName());
vo.setPicture(userInfo.getPicture());
vo.setEmail(userInfo.getEmail());
vo.setEmailVerified(userInfo.isEmailVerified());
vo.setLocale(userInfo.getLocale());
result.setResult(vo);
} catch (Exception e) {
}
return result;
}
}
▷ GoogleOAuthTokenVO.java
/**
* [구글] 토큰 발급 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "[구글] 토큰 발급 응답 VO")
@JsonIgnoreProperties(ignoreUnknown = true)
public class GoogleOAuthTokenVO {
@JsonProperty("access_token")
@Schema(description = "애플리케이션에서 Google API 요청을 승인하기 위해 보내는 토큰입니다.")
public String access_token;
@JsonProperty("refresh_token")
@Schema(description = "새 액세스 토큰을 얻는 데 사용할 수 있는 토큰입니다. 갱신 토큰은 사용자가 액세스 권한을 취소할 때까지 유효합니다.")
public String refresh_token;
}
▷ GoogleUserInfoVO.java
/**
* [구글] 사용자 정보 조회 응답 VO
*/
@Getter
@Setter
@ToString
@Schema(description = "[구글] 사용자 정보 조회 응답 VO")
@JsonIgnoreProperties(ignoreUnknown = true)
public class GoogleUserInfoVO {
@JsonProperty("sub")
@Schema(description = "사용자의 고유 식별자. 모든 Google 계정에서 유일하며 재사용되지 않습니다.")
public String sub;
@JsonProperty("name")
@Schema(description = "사용자의 전체 이름 (표시 가능한 형식).")
public String name;
@JsonProperty("given_name")
@Schema(description = "사용자의 이름.")
public String givenName;
@JsonProperty("family_name")
@Schema(description = "사용자의 성.")
public String familyName;
@JsonProperty("picture")
@Schema(description = "사용자의 프로필 사진 URL.")
public String picture;
@JsonProperty("email")
@Schema(description = "사용자의 이메일 주소. 이 값은 유일하지 않을 수 있으며 시간이 지남에 따라 변경될 수 있습니다.")
public String email;
@JsonProperty("email_verified")
@Schema(description = "사용자의 이메일 주소가 확인되었는지 여부. true일 경우 이메일이 확인된 상태입니다.")
public boolean emailVerified;
@JsonProperty("locale")
@Schema(description = "사용자의 언어 및 국가 정보. BCP 47 언어 태그 형식으로 제공됩니다.")
public String locale;
}
▷ GoogleApiService.java
/**
* 구글 API Service
*
* https://developers.google.com/identity/protocols/oauth2?hl=ko
*/
public interface GoogleApiService {
/** [구글] 토큰 발급 **/
public GoogleOAuthTokenVO getOAuthToken(String code);
/** [구글] 사용자 정보 조회 **/
public GoogleUserInfoVO getUserInfo(String accessToken);
}
▷ GoogleApiServiceImpl.java
/**
* 구글 API ServiceImpl
*
*/
@Slf4j
@Service
public class GoogleApiServiceImpl implements GoogleApiService {
@Value("${google.client.id}")
private String GOOGLE_CLIENT_ID;
@Value("${google.client.secret}")
private String GOOGLE_API_SECRET;
@Value("${google.redirect.uri}")
private String GOOGLE_REDIRECT_URI;
/**
* [구글] 토큰 발급
*/
@Override
public GoogleOAuthTokenVO getOAuthToken(String code) {
GoogleOAuthTokenVO result = new GoogleOAuthTokenVO();
try {
log.info("[구글] 토큰 발급 시작");
if (code == null) {
return result;
}
/* 요청 */
final String uri = "https://oauth2.googleapis.com/token";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // MultiValueMap
MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
body.add("grant_type", "authorization_code");
body.add("client_id", GOOGLE_CLIENT_ID);
body.add("client_secret", GOOGLE_API_SECRET);
body.add("redirect_uri", GOOGLE_REDIRECT_URI);
body.add("code", code);
/* 응답 */
ResponseEntity<String> res = new RestTemplate().postForEntity(uri, new HttpEntity<>(body, headers),
String.class);
result = new ObjectMapper().readValue(res.getBody(), GoogleOAuthTokenVO.class);
log.info("[구글] 토큰 발급 종료");
} catch (Exception e) {
}
return result;
}
/**
* [구글] 사용자 정보 조회
*/
@Override
public GoogleUserInfoVO getUserInfo(String accessToken) {
GoogleUserInfoVO result = new GoogleUserInfoVO();
try {
log.info("[구글] 사용자 정보 조회 시작");
if (accessToken == null) {
return result;
}
/* 요청 */
final String uri = "https://www.googleapis.com/oauth2/v3/userinfo";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); // MultiValueMap
headers.add("Authorization", "Bearer " + accessToken);
/* 응답 */
ResponseEntity<String> res = new RestTemplate().postForEntity(uri, new HttpEntity<>(headers), String.class);
result = new ObjectMapper().readValue(res.getBody(), GoogleUserInfoVO.class);
log.info("[구글] 사용자 정보 조회 종료");
} catch (Exception e) {
}
return result;
}
}
▷ 결과
▷ 관련 글
SNS 간편로그인 - 구글 API 사용 등록 방법
구글 Open API를 사용하기 위한 구글 developers 사용 설정*자세한 설명 생략 ▷ 구글 API 사용 등록 방법 ⓛ 프로젝트 생성 Google 클라우드 플랫폼로그인 Google 클라우드 플랫폼으로 이동accounts.goog
coding-today.tistory.com
RestTemplate Post 요청 보내기
RestTemplate로 Post 요청을 보내고, 응답 코드를 확인하는 메서드*Header 값(Authorization)만 추가하고, Body는 빈 값으로 요청*자세한 설명 생략 /** * POST 요청 */public static boolean sendPost(String jwt) { boolean r
coding-today.tistory.com
Objcet to String
Object를 String으로 변환하는 간단한 방법 /** * * Object to String * * @param Object * @return String */ public static String getObjStr(Object obj) { String str = ""; try { str = new ObjectMapper().writeValueAsString(obj); } catch (Exception e)
coding-today.tistory.com
JSON Unrecognized field 해결방법(@JsonIgnoreProperties)
JSON 데이터를 구성하는 요소가 가변적일 때 무시하는 방법 *소스는 변하지 않았지만 연동 했던 API 응답 값이 변했다고 가정 ▷ ERROR - JSON 데이터를 매핑하지 못해 에러 발생 com.fasterxml.jackson.databi
coding-today.tistory.com
SNS 간편로그인 - 카카오 API 사용 등록 방법
카카오 Open API를 사용하기 위한 카카오 developers 앱 등록*자세한 설명 생략 ▷ 카카오 API 사용 등록 방법 ① 내 애플리케이션 생성 Kakao Developers카카오 API를 활용하여 다양한 어플리케이션을
coding-today.tistory.com
SNS 간편로그인 - 네이버 API 사용 등록 방법
네이버 Open API를 사용하기 위한 네이버 developers 앱 등록*자세한 설명 생략 ▷ 네이버 API 사용 등록 방법 ① 내 애플리케이션 생성 애플리케이션 - NAVER Developers developers.naver.com ▷ 관련 글 S
coding-today.tistory.com
▷ 참고
OAuth 2.0 홈 | Apigee | Google Cloud
projects.locations.apis.versions.definitions
cloud.google.com
OAuth 2.0을 사용하여 Google API에 액세스하기 | Authorization | Google for Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 OAuth 2.0을 사용하여 Google API에 액세스하기 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요.
developers.google.com
웹 서버 애플리케이션용 OAuth 2.0 사용 | Authorization | Google for Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 웹 서버 애플리케이션용 OAuth 2.0 사용 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. 이
developers.google.com
OpenID Connect | Authentication | Google for Developers
이 페이지는 Cloud Translation API를 통해 번역되었습니다. 의견 보내기 OpenID Connect 컬렉션을 사용해 정리하기 내 환경설정을 기준으로 콘텐츠를 저장하고 분류하세요. Google의 OAuth 2.0 API는 인증과 승
developers.google.com
'▶ Back-End > Java' 카테고리의 다른 글
Null Check and Default Value (0) | 2024.08.20 |
---|---|
SNS 간편로그인 - 네이버 로그인 API 호출 및 사용자 정보 받기 (0) | 2024.07.16 |
SNS 간편로그인 - 카카오 로그인 API 호출 및 사용자 정보 받기 (0) | 2024.07.11 |
RestTemplate Post 요청 보내기 (0) | 2024.07.04 |
LocalDate Jackson Data Format 변경 (0) | 2023.11.23 |
댓글