2017 - 11 - 30 (목)
네이버 로그인
1 . 네이버 개발자 센터에서 어플리케이션을 등록합니다.
2 . 네이버 어플리케이션 ID 와 SECRET 코드를 저장해 둡니다.
3 . pom.xml 에 아래 코드를 추가
<dependency>
<groupId>com.github.scribejava</groupId>
<artifactId>scribejava-core</artifactId>
<version>3.3.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.3</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.3</version>
</dependency>
4 . com/bitproject/naver/NaverLoginBO 생성
package com.bitproject.naver;
import java.io.IOException;
import java.util.UUID;
import javax.servlet.http.HttpSession;
public class NaverLoginBO {
private final static String CLIENT_ID = "네이버 앱아이디";
private final static String CLIENT_SECRET = "네이버 시크릿코드";
private final static String REDIRECT_URI = "http://localhost/login/callback";
private final static String SESSION_STATE = "oauth_state";
/* 프로필 조회 API URL */
private final static String PROFILE_API_URL = "https://openapi.naver.com/v1/nid/me";
/* 네아로 인증 URL 생성 Method */
public String getAuthorizationUrl(HttpSession session) {
/* 세션 유효성 검증을 위하여 난수를 생성 */
String state = generateRandomString();
/* 생성한 난수 값을 session에 저장 */
setSession(session,state);
/* Scribe에서 제공하는 인증 URL 생성 기능을 이용하여 네아로 인증 URL 생성 */
OAuth20Service oauthService = new ServiceBuilder()
.apiKey(CLIENT_ID)
.apiSecret(CLIENT_SECRET)
.callback(REDIRECT_URI)
.state(state)
.build(NaverLoginApi.instance());
return oauthService.getAuthorizationUrl();
}
/* 네아로 Callback 처리 및 AccessToken 획득 Method */
public OAuth2AccessToken getAccessToken(HttpSession session, String code, String state) throws IOException{
/* Callback으로 전달받은 세선검증용 난수값과 세션에 저장되어있는 값이 일치하는지 확인 */
String sessionState = getSession(session);
if(StringUtils.pathEquals(sessionState, state)){
OAuth20Service oauthService = new ServiceBuilder()
.apiKey(CLIENT_ID)
.apiSecret(CLIENT_SECRET)
.callback(REDIRECT_URI)
.state(state)
.build(NaverLoginApi.instance());
/* Scribe에서 제공하는 AccessToken 획득 기능으로 네아로 Access Token을 획득 */
OAuth2AccessToken accessToken = oauthService.getAccessToken(code);
return accessToken;
}
return null;
}
/* 세션 유효성 검증을 위한 난수 생성기 */
private String generateRandomString() {
return UUID.randomUUID().toString();
}
/* http session에 데이터 저장 */
private void setSession(HttpSession session,String state){
session.setAttribute(SESSION_STATE, state);
}
/* http session에서 데이터 가져오기 */
private String getSession(HttpSession session){
return (String) session.getAttribute(SESSION_STATE);
}
/* Access Token을 이용하여 네이버 사용자 프로필 API를 호출 */
public String getUserProfile(OAuth2AccessToken oauthToken) throws IOException{
OAuth20Service oauthService =new ServiceBuilder()
.apiKey(CLIENT_ID)
.apiSecret(CLIENT_SECRET)
.callback(REDIRECT_URI).build(NaverLoginApi.instance());
OAuthRequest request = new OAuthRequest(Verb.GET, PROFILE_API_URL, oauthService);
oauthService.signRequest(oauthToken, request);
Response response = request.send();
return response.getBody();
}
}
5 . com/bitproject/naver/NaverLoginApi 생성
package com.bitproject.naver;
import com.github.scribejava.core.builder.api.DefaultApi20;
public class NaverLoginApi extends DefaultApi20 {
protected NaverLoginApi() {
}
private static class InstanceHolder {
private static final NaverLoginApi INSTANCE = new NaverLoginApi();
}
public static NaverLoginApi instance() {
return InstanceHolder.INSTANCE;
}
@Override
public String getAccessTokenEndpoint() {
return "https://nid.naver.com/oauth2.0/token?grant_type=authorization_code";
}
@Override
protected String getAuthorizationBaseUrl() {
return "https://nid.naver.com/oauth2.0/authorize";
}
}
6 . servlet-context.xml 에 빈 등록
<beans:bean id="naverLoginBO" class="com.bitproject.naver.NaverLoginBO" />
7 . userController에 user/naverLogin 에 매핑되는 매서드와 user/callback 추가
private NaverLoginBO naverLoginBO;
private String apiResult = null;
/* NaverLoginBO */
@Inject
private void setNaverLoginBO(NaverLoginBO naverLoginBO) {
this.naverLoginBO = naverLoginBO;
}
@RequestMapping(value="/naverLogin", method = RequestMethod.GET)
public ModelAndView login(HttpSession session) {
/* 네아로 인증 URL을 생성하기 위하여 getAuthorizationUrl을 호출 */
String naverAuthUrl = naverLoginBO.getAuthorizationUrl(session);
System.out.println("controller 호출");
return new ModelAndView("user/naverLogin", "url", naverAuthUrl);
}
@RequestMapping(value="/callback",method = RequestMethod.GET)
public ModelAndView callback(@RequestParam String code, @RequestParam String state, HttpSession session) throws IOException {
/* 네아로 인증이 성공적으로 완료되면 code 파라미터가 전달되며 이를 통해 access token을 발급 */
OAuth2AccessToken oauthToken = naverLoginBO.getAccessToken(session, code, state);
apiResult = naverLoginBO.getUserProfile(oauthToken);
// System.out.println(apiResult);
JSONObject jsonobj = jsonparse.stringToJson(apiResult, "response");
String sex = jsonparse.JsonToString(jsonobj, "gender");
String snsId = jsonparse.JsonToString(jsonobj, "id");
String name = jsonparse.JsonToString(jsonobj, "name");
UserVO vo = new UserVO();
vo.setUser_snsId(snsId);
vo.setUser_name(name);
System.out.println(name);
try {
vo = service.naverLogin(vo);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
session.setAttribute("login",vo);
return new ModelAndView("user/loginPost", "result", vo);
}
이 때 페이스북 로그인과 마찬가지로 서비스를 통해 DAO로 데이터베이스에 값을 넣어준다.
8 . user/loginPost.jsp , user/callback.jsp 작성
- loginPost.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<title>NaverLogin</title>
</head>
<body>
<script>
self.location = '${url}';
</script>
</body>
</html>
- callback.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<html>
<head>
<title>NaverLoginTest</title>
</head>
<body>
<br>
<div style="text-align:center">${result}</div>
</body>
</html>
JSON to String / String to JSON
9 . 네이버에서 정보를 받을때 String 타입으로 값을 받는데 이 형태가 JSON 과 같다. JSON 안에 JSON 값을 가지고 있다. 이 부분을 객체로 변환하기 위해 String 형태로 변환시킬 필요가 있었다.
- pom.xml 에서 라이브러리 추가한다.
<!-- json simple -->
<!-- https://mvnrepository.com/artifact/com.github.jsurfer/jsurfer-jsonsimple -->
<dependency>
<groupId>com.github.jsurfer</groupId>
<artifactId>jsurfer-jsonsimple</artifactId>
<version>1.4.1</version>
</dependency>
- 스트링 타입의 json 데이터 키의 값중 json 형태인 값을 JSON 타입으로 변환하여 반환하는 메서드와 json 타입의 키 값을 스트링으로 반환하는 메서드를 정의한다.
package com.bitproject.common;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;
public class JsonStringParse {
public JSONObject stringToJson(String jsonStr, String key) {
JSONParser parser = new JSONParser();
Object obj = null;
try {
obj = parser.parse(jsonStr);
} catch (ParseException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
JSONObject jsonobj = (JSONObject) obj;
JSONObject response = (JSONObject) jsonobj.get(key);
//
// String profile = (String)response.get("gender");
// System.out.println(profile);
//
return response;
}
public String JsonToString(JSONObject jsonobj, String key) {
String str = (String)jsonobj.get(key);
return str;
}
}