JSP/Servlet으로 카카오 로그인 구현하기

  • 프로젝트 진행하면서 OAuth구현 했던것을 정리하고자 남김
  • 대부분의 구현이 Javascript, Spring이라서 각종 소스를 긁어와서 합친 글임을 밝힙니다

OAuth에 대한 포스팅이 궁금하다면 이 포스트를 먼저 보세요

https://puzzle-making.tistory.com/97

https://itstudy-mary.tistory.com/m/148?category=920400에서 도움을 많이 받았습니다. 감사합니다.

  • 카카오 로그인 구현의 핵심
1. 카카오 Developer페이지에서 환경설정
2. 요청을 보내서 인가코드 받아오기
3. 받아온 인가코드로 access_token 받아오기
4. access_token 활용해서 사용자 정보 받아오기
5. 받아온 정보로 로그인/회원가입 진행

혹시나 다른 언어나 라이브러리로 카카오 로그인 구현을 한다면 저 단계를 생각하면서

구현을 해본다면 충분히 할 수 있으리라 생각한다.

카카오 Developer 환경설정

모든 진행은 https://developers.kakao.com/ 사이트에서 진행된다.

환경설정에 대한 자세한 포스트는 구글링을 해보면 많이 나오니 과감하게 스킵하겠다.

이 과정에서 신경써야 할것은 [앱 키]를 받아오는 것과 [카카오 로그인 활성화] [Redirect URI] 설정이다.

요청을 보내서 인가코드 받아오기

제목에서처럼 JSP/Servlet을 활용한 방법이니까 loginForm.jsp에서 출발한다.

loginForm.jsp는 로그인을 위한 jsp파일이며 [카카오톡 로그인]을 클릭했을때

카카오 로그인을 처리하는 KakaoLoginServlet으로 이동하게 세팅 했다.

여기서 이동할때 [앱키]와 [Redirect url]을 통해 카카오에 요청을 보내서 [인가코드] 받아오는 것이 핵심이다.

  • loginForm.jsp
<a href="https://kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri=http://localhost:8079/Dong-Dong/kakao&response_type=code">
<img height="35px" src="images/kakao_login_button.png" /></a>

{REST_API_KEY} 부분에 본인이 부여받은 REST API키를 입력하면 되고 redirect url도 본인이 설정해 놓은 주소로 입력하면된다. 나는 servlet주소를 kakao로 바꿔놓았다.

a태그로 redirect url로 이동하게 만들었고 이 과정에서 파라미터로 code가 넘어올 예정이다.

받아온 인가코드로 access_token 받아오기

  • KakaoLoginServlet

가장 먼저 인가코드를 받았는지 확인한다.

String code = request.getParameter("code");

인가코드가 넘어왔다면 이 코드를 통해 access토큰을 받아야한다.

이 때 grant_type, client_id(앱키), redirect_url, code(인가코드)를 담아서 함께 보내주어야 하는데 이부분에서 많이 해맸었다.

request

String bodyData="grant_type=authorization_code&";
        bodyData += "client_id={앱키}&";
        bodyData += "redirect_uri=http://localhost:8079/Dong-Dong/kakao&";
        bodyData += "code="+code; //인가코드


        URL url = new URL(pUrl);
        HttpURLConnection con = (HttpURLConnection) url.openConnection();
        con.setRequestMethod("POST");
        con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
        con.setDoOutput(true);

        BufferedWriter bw=new BufferedWriter(new OutputStreamWriter(con.getOutputStream(),"UTF-8"));
        bw.write(bodyData);
        bw.flush();          
  • 먼저 다시한번 REST API로 POST요청을 해야하기 때문에 HttpURLConnection을 이용해 네트워크 길을 뚫어준다.
  • content_type은 카카오에서 정해준대로 세팅해주고 setDoOuput으로 서버 통신에서 출력 가능한 상태로 만들어 준다.
  • 우리는 추가적으로 데이터를 더 보내줘야 하므로 BufferedWriter로 버퍼에 보내줄 데이터를 모은다음(bw.write) 한번에 flush해줘야한다.(bw.flush)
  • 여기까지하면 request 완료

response

BufferedReader br = new BufferedReader(
                    new InputStreamReader(con.getInputStream(), "UTF-8")
                    );
String input="";
StringBuilder sb=new StringBuilder();
while((input=br.readLine())!=null){
            sb.append(input);
}

Gson gson=new Gson();            
OAuthTokenDTO oAuthToken=gson.fromJson(sb.toString(), OAuthTokenDTO.class);
  • BufferedReader로 response를 받아주는 과정이다.
  • 받아오는 데이터가 뭉텅이로 넘어오는것이 아니기 때문에 StringBuilder로 차곡차곡 쌓아준다
  • 데이터는 Json형태로 받아오기때문에 처리를 위해 Gson을 사용한다.
  • Gson을 처음 사용해보는 사용자라면 Gson.jar파일을 lib 폴더에 추가해야 사용이 가능하다.
  • 받아온 json 형태에서 객체로 바로 저장할 수 있게끔 OAuthTokenDTO를 만들어 주었고
  • 저 객체에 access_token을 비롯한 자료들을 모두 저장해주었다.
public class OAuthTokenDTO {
    private String access_token;
    private String token_type;
    private String refresh_token;
    private int expires_in;
    private String scope;
    private int refresh_token_expires_in;
  • 받아오는 데이터들
Key
Name Type Description
token_type String 토큰 타입, bearer로 고정
access_token String 사용자 액세스 토큰 값
expires_in Integer 액세스 토큰 만료 시간(초)
refresh_token String 사용자 리프레시 토큰 값
refresh_token_expires_in Integer 리프레시 토큰 만료 시간(초)
scope String 인증된 사용자의 정보 조회 권한 범위 범위가 여러 개일 경우, 공백으로 구분
  • 여기서 받아온 access_token을 활용해서 유저 정보를 받아올 것이다.

유저정보 받아오기

request/response

String kurl="https://kapi.kakao.com/v2/user/me";
URL url2 =new URL(kurl);

HttpsURLConnection con2=(HttpsURLConnection)url2.openConnection();

//header 값 넣기
con2.setRequestProperty("Authorization", "Bearer "+oAuthToken.getAccess_token());
            con2.setDoOutput(true);

//request 하기
BufferedReader br2=new BufferedReader(new InputStreamReader(con2.getInputStream(),"UTF-8"));
String input2="";
StringBuilder sb2=new StringBuilder();
while((input2=br2.readLine())!=null) {
            sb2.append(input2);
}

Gson gson2=new Gson();
KakaoProfileDTO kakaoProfile=gson2.fromJson(sb2.toString(),KakaoProfileDTO.class);
  • 아까처럼 똑같이 HttpsURLConnection을 이용해서 길을 뚫어주고 요청을 보낸다
  • 아까랑은 다르게 많은 데이터를 같이 보내줄 필요가 없어서 property에 access_token만 담아서 보내줌
  • request받아오는 과정은 위와 비슷합니다.
  • 이번에도 KakaoProfileDTO를 만들어서 받아오는 정보를 담기 위한 객체를 따로 생성해 주었습니다.

최종로그인

String userid = kakaoProfile.getId() + "_kakao";
String passwd = kakaoProfile.getId();
String email = kakaoProfile.getKakao_account().getEmail();

HashMap<String, String> map = new HashMap<String, String>();
map.put("userid", userid);
map.put("passwd", passwd);

MemberService service = new MemberService();
MemberDTO dto = service.login(map);
  • 카카오에서 로그인하는 유저임을 확인하기 위해 아이디 뒤에는 _kakao를 붙여서 구분지어 줬습니다. map에 id/pw 정보를 담아서 DB에 회원정보가 있으면 로그인 성공, 회원 정보가 없다면 회원가입 과정이 진행될 수 있게 설정했습니다.

+ Recent posts