์ด๋ฒ ์๊ฐ์๋ ์นด์นด์ค ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์์๋ณด๊ฒ ์ต๋๋ค. :D
์ฐธ๊ณ :
- ๊ตฌ๊ธ ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ์๊ธฐ ๋ฐ๋๋๋ค.
- ๋ค์ด๋ฒ ๊ณ์ ์ผ๋ก ๋ก๊ทธ์ธ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ์๊ธฐ ๋ฐ๋๋๋ค.
- ์์ ๋ก๊ทธ์ธ์ ํ๊ธฐ์ํด ํ์ํ API ํค ๋ฐ๊ธ์ ์ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ์๊ธฐ ๋ฐ๋๋๋ค.
์นด์นด์ค ๋ก๊ทธ์ธ ๋ฒํผ ๊ตฌํํ๊ธฐ
์ผ๋จ ์นด์นด์ค์์ ์ ๊ณตํ๋ ๋ก๊ทธ์ธ ๋ฒํผ์ ๋ฐ์์ ์ฌ์ฉํ๊ฒ ์ต๋๋ค.
์ด๋ฏธ์ง๋ฅผ ๋ค์ด ๋ฐ์์ผ๋ฉด, ์ด์ ๋ฒํผ์ ๋งํฌ๋ฅผ ๋ฌ๋ฉด ๋ฉ๋๋ค.
Request ์์ฒญ ๋งํฌ
{REST_API_KEY} ๋ถ๋ถ์๋ ์ฑ ์์ฑ ์ ๋ฐ๊ธ๋ฐ์ REST API ํค๋ฅผ ๋ฃ์ด์ฃผ๋ฉด ๋๊ณ , ๋๋จธ์ง๋ ์๋ ํ๋ฅผ ๋ณด๊ณ ์๋ง๊ฒ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
URL์ ์๊น ๋ฐ์ ์ด๋ฏธ์ง์ ํจ๊ป ๋ฃ์ด์ค๋๋ค. (๋ฐ๊ธ ๋ฐ์ผ์ client_id๋ uri๋ ์ง์ ๋ฃ์ผ์ ์ผํฉ๋๋ค.)
<a href="https://kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code"><img src="/image/kakao_login_medium.png"></a>
๊ทธ๋ฆฌ๊ณ ์คํํด๋ณด๋ฉด,
์ด๋ ๊ฒ ์นด์นด์ค ์ ๋ณด ๋์ ํ๋ฉด์ด ๋จ๊ฒ ๋๋๋ฐ, ์ด๊ฑด ์ด๋ฏธ ๋ก๊ทธ์ธ์ ํ ์ํ๋ผ ๊ทธ๋ ์ต๋๋ค.
๋ก๊ทธ์์์ ํด๋ณด๊ณ ์คํํด๋ณด๋ฉด ์ด๋ป๊ฒ ๋ ๊น์?
์ด๋ ๊ฒ ๋ก๊ทธ์ธ์ ํ๋ ํ์ด์ง๊ฐ ๋์ค๊ฒ ๋ฉ๋๋ค.
๋ก๊ทธ์ธ์ ํ๊ณ [๋์ํ๊ณ ๊ณ์ํ๊ธฐ] ๋ฅผ ํด๋ฆญํ๋ค๋ฉด?
์ฐ๋ฆฌ๊ฐ ์ค์ ํ Redirect URI๋ก ์๋ต์ด ์ค๊ฒ ๋๋๋ฐ, ๋ค์ code๋ฅผ ๊ฐ์ง๊ณ ์๋ต์ด ์ค๊ฒ ๋ฉ๋๋ค. ์ด ์ฝ๋๊ฐ ์์ผ๋ฉด ์ ์์ ์ผ๋ก ์ธ์ฆ์ด ๋๋ค๋ ๋ป์ ๋๋ค. (404 ์๋ฌ๊ฐ ๋จ๋ ์ด์ ๋ ํด๋น url ์ปจํธ๋กค๋ฌ๋ฅผ ๋ง๋ค์ง ์์๊ธฐ ๋๋ฌธ์ ๋๋ค.)
์ปจํธ๋กค๋ฌ ์์ฑ
MemberOauth2Controller๋ผ๊ณ ํด๋์ค๋ฅผ ๋ง๋ค์์ต๋๋ค.
@RestController
@RequestMapping(value = "/login/oauth2/code")
public class MemberOauth2Controller {
@GetMapping(value = "/kakao")
public String kakaoOauthRedirect(@RequestParam String code) {
return "์นด์นด์ค ๋ก๊ทธ์ธ ์ธ์ฆ ์๋ฃ, code : " + code;
}
}
@RequestParam์ ํ๋ผ๋ฏธํฐ์ ํ์ ์ด ๊ธฐ๋ณธ ํ์ ์ด๊ฑฐ๋ ์ฟผ๋ฆฌ ์คํธ๋ง์ ๊ธฐ๋ณธ ํ์ ์ธ String์ธ ๊ฒฝ์ฐ ์ด๋ ธํ ์ด์ ์๋ต ๊ฐ๋ฅํฉ๋๋ค.
Response :
http://localhost:8080/login/oauth2/code/kakao?code={AUTHORIZE_CODE}
์ฑ๊ณต์ ์ผ๋ก ์ธ๊ฐ ์ฝ๋๋ฅผ ๋ฐ์์ต๋๋ค.
์์ธ์ค ํ ํฐ ๋ฐ๊ธ ๋ฐ๊ธฐ
์ด์ ์ ๋ฐ์๋ ์ธ๊ฐ ์ฝ๋๋ฅผ ์ด์ฉํด์ ๊ณ์ ์ ๋ณด์ ์ ๊ทผํ ์ ์๋ Access Token์ ๋ฐ์ ๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์์ ๋ฌธ์์ฒ๋ผ ์์ฒญ์ ๋ณด๋ด๋ฉด ๋ฉ๋๋ค.
Request:
// ์นด์นด์ค์ POST๋ฐฉ์์ผ๋ก key=value ๋ฐ์ดํฐ๋ฅผ ์์ฒญํจ. RestTemplate๋ฅผ ์ฌ์ฉํ๋ฉด ์์ฒญ์ ํธํ๊ฒ ํ ์ ์๋ค.
RestTemplate rt = new RestTemplate();
// HttpHeader ์ค๋ธ์ ํธ ์์ฑ
HttpHeaders headers = new HttpHeaders();
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
// HttpBody ์ค๋ธ์ ํธ ์์ฑ
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("grant_type", "authorization_code");
params.add("client_id", "{client_id}");
params.add("redirect_uri", "http://localhost:8080/login/oauth2/code/kakao");
params.add("code", code);
params.add("client_secret", "{secret_code}");
// HttpHeader์ HttpBody๋ฅผ HttpEntity์ ๋ด๊ธฐ (why? rt.exchange์์ HttpEntity๊ฐ์ฒด๋ฅผ ๋ฐ๊ฒ ๋์ด์๋ค.)
HttpEntity<MultiValueMap<String, String>> kakaoRequest = new HttpEntity<>(params, headers);
// HTTP ์์ฒญ - POST๋ฐฉ์ - response ์๋ต ๋ฐ๊ธฐ
ResponseEntity<String> response = rt.exchange(
"https://kauth.kakao.com/oauth/token",
HttpMethod.POST,
kakaoRequest,
String.class
);
์์ฒญ์ ์ฝ๊ฒ ๋ณด๋ผ ์ ์๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๊ฐ ์๋๋ฐ, ๊ทธ ์ค ํ๋๊ฐ RestTemplate ์ ๋๋ค.
HttpHeaders๋ฅผ ์์ฑํด์ ํค๋์ ๊ฐ์ ๋ฃ์ด์ฃผ๊ณ , MultiValueMap์ ์ด์ฉํด์ key:value ๋ฐ์ดํฐ ํ์์ผ๋ก ๊ฐ์ ๋ฃ์ด์ค๋๋ค.
๊ทธ๋ฆฌ๊ณ , HttpEntity์ ๋ฐ๋ ๋ถ๋ถ์ ํด๋น๋๋ MultiValueMap์ ๋ฃ์ด์ค๋๋ค. (์์ฒญ์ ๋ณด๋ผ ๋, HttpEntity๋ฅผ ๋ฃ์ด์ผ ํ๊ธฐ ๋๋ฌธ์ ํ๋ฒ ๋ ๊ฐ์ผ ํํ์ ๋๋ค.) ์ด์ kakaoRequest๋ ๋ฐ๋, ํค๋๋ฅผ ๋ ๋ค ๊ฐ์ง๊ณ ์๋ ์ธ์คํด์ค๊ฐ ๋ฉ๋๋ค.
Response:
์ ์์์ฒ๋ผ ์๋ต์ด ์์ผ๋ฉด, ์ด์ ๊ณ์ ์ ๋ณด์ ์ ๊ทผํ๊ธฐ ์ํด ํ์ํ access_token์ ๋ฐ์์ต๋๋ค!
์ฌ์ฉ์ ์ ๋ณด ๊ฐ์ ธ์ค๊ธฐ
์์ฒญ์ ์์ ๊ฐ์ด ํ์๋ฉด ๋ฉ๋๋ค.
Request:
// ์ฌ๊ธฐ์๋ถํฐ, Access Token์ ์ด์ฉํด์ ์ฌ์ฉ์ ์ ๋ณด๋ฅผ ์๋ต ๋ฐ๋ ์ฝ๋์ด๋ค.
HttpHeaders headers1 = new HttpHeaders();
headers1.add("Authorization", "Bearer " + kakaoOauthParams.getAccess_token());
headers1.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
HttpEntity<HttpHeaders> kakaoRequest1 = new HttpEntity<>(headers1);
ResponseEntity<String> profileResponse = rt.exchange(
"https://kapi.kakao.com/v2/user/me",
HttpMethod.POST,
kakaoRequest1,
String.class
);
kakaoOauthParams.getAccess_token() ์ด ๋ถ๋ถ์ ์์์ ๋ฐ์ ์๋ต์ ObjectMaper๋ฅผ ์ด์ฉํด์ ๊ฐ์ฒด์ ๋ด์์ ๊ฐ์ ์ฌ์ฉํ์ต๋๋ค.
์ฑ๊ณตํ์๋ฉด, ์๋์ ๊ฐ์ด ์๋ต์ ๋ฐ์ ์ ์์ต๋๋ค.
๊ฐ์ฌํฉ๋๋ค~