문의 시, 사용하시는 개발환경과 디벨로퍼스 앱ID를 알려주세요.
앱아이디 : 964154
package com.semi.main.kakao;
import java.io.IOException;
import javax.servlet.http.HttpSession;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
import org.springframework.beans.factory.annotation.Autowired;
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.ui.Model;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestTemplate;
import com.semi.main.member.MemberDTO;
@Controller
@RequestMapping("/kakao/*")
public class KakaoController {
@Autowired
private KakaoService kakaoService;
// 로그인: 인가 코드 및 토큰 발급
@RequestMapping(value = "callback", method = RequestMethod.GET)
public String getLogin(@RequestParam("code") String code, HttpSession session, Model model) throws Exception{
// 1. header 생성
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded;charset=utf-8");
// 2. body 생성
MultiValueMap<String, String> params = new LinkedMultiValueMap<String, String>();
params.add("grant_type", "authorization_code"); //고정값
params.add("client_id", "d5aa1769209cd0342601e6c69c838176");
params.add("redirect_uri", "http://localhost:82/kakao/callback"); //등록한 redirect uri
params.add("code", code);
// 3. header + body
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<MultiValueMap<String, String>>(params, httpHeaders);
// 4. http 요청하기
RestTemplate restTemplate = new RestTemplate();
ResponseEntity<String> response = restTemplate.exchange(
"https://kauth.kakao.com/oauth/token",
HttpMethod.POST,
httpEntity,
String.class
);
System.out.println("1111");
JSONParser jsonParser = new JSONParser();
JSONObject jsonObj = (JSONObject) jsonParser.parse(response.getBody());
String accessToken = (String) jsonObj.get("access_token");
// 발급받은 토큰 정보로 유저 정보를 얻어옴
MemberDTO memberDTO = getUserInfoWithToken(accessToken);
MemberDTO memberDTO2 = kakaoService.getEmailCheck(memberDTO);
System.out.println(memberDTO2);
if(memberDTO2 != null) {
//4. 세션에 저장
System.out.println("기존 정보 있음");
session.setAttribute("member", memberDTO2);
return "/member/login";
}else {
System.out.println("기존 정보 없음");
session.setAttribute("kakaoMember", memberDTO);
return "/member/signUp";
}
}
private MemberDTO getUserInfoWithToken(String accessToken) throws ParseException {
//HttpHeader 생성
HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Bearer " + accessToken);
headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");
//HttpHeader 담기
RestTemplate rt = new RestTemplate();
HttpEntity<MultiValueMap<String, String>> httpEntity = new HttpEntity<>(headers);
ResponseEntity<String> response = rt.exchange(
"https://kapi.kakao.com/v2/user/me",
HttpMethod.POST,
httpEntity,
String.class
);
//Response 데이터 파싱
JSONParser jsonParser = new JSONParser();
JSONObject jsonObj = (JSONObject) jsonParser.parse(response.getBody());
JSONObject account = (JSONObject) jsonObj.get("kakao_account");
String email = String.valueOf(account.get("email"));
MemberDTO memberDTO = new MemberDTO();
memberDTO.setEmail(email);
return memberDTO;
}
}
입 예외 보고
메시지 Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
설명 서버가, 해당 요청을 충족시키지 못하게 하는 예기치 않은 조건을 맞닥뜨렸습니다.
예외
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:982)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
근본 원인 (root cause)
org.springframework.web.client.HttpClientErrorException: 401 Unauthorized
org.springframework.web.client.DefaultResponseErrorHandler.handleError(DefaultResponseErrorHandler.java:91)
org.springframework.web.client.RestTemplate.handleResponse(RestTemplate.java:667)
org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:620)
org.springframework.web.client.RestTemplate.execute(RestTemplate.java:580)
org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:498)
com.semi.main.kakao.KakaoController.getLogin(KakaoController.java:54)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.base/java.lang.reflect.Method.invoke(Method.java:566)
org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:221)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:136)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:114)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861)
javax.servlet.http.HttpServlet.service(HttpServlet.java:529)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
javax.servlet.http.HttpServlet.service(HttpServlet.java:623)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
비고 근본 원인(root cause)의 풀 스택 트레이스를, 서버 로그들에서 확인할 수 있습니다.
해당컨트롤러 사용하고 있는데 소셜로그인시 동의후 로그인누르면 401에러가 발생합니다. 무엇이 문제인지 알수잇을까요 감이안잡힙니다 리다이렉트주소도 알맞게 설정되어있는데 안되는이유를 모르겠습니다.