twocowsong

네이버 로그인 API 본문

IT/기타

네이버 로그인 API

WsCode 2022. 2. 22. 13:40

웹 환경 - Java, SpringBoot

 

순서

1. 네이버 개발자에서 애플리케이션 등록

  https://developers.naver.com/main/

 

NAVER Developers

네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음

developers.naver.com

2. SDK 설정 및 화면 셋팅 (네이버의 경우 버튼 이미지를 호출하는방식이 다른 SNS와 다릅니다.)

3. 서버에서 API를 통한 AccessToken 검증


1. 네이버 개발자에서 애플리케이션 등록

1번 바로가기를 통해 네이버 개발자에서 로그인을 해주세요. 그 후 애플리케이션 등록 화면으로 이동하여 이름과 사용 API의 선택하세요를 클릭 후 네이버 로그인을 선택하시면 아래와같이 체크박스 목록이 출력됩니다. 여기서 체크한 항목은 사용자가 네이버로그인을 하고나면 제공받을수있습니다.

 

하지만! 네이버의 경우 필수목록을 필수라고 하여도 필수가아닙니다. (이게 뭔말이야...)

네이버 로그인을 하실때보시면 아래와 같은 로그인 창을 보실수있습니다.

필수라고 해놓고 체크를 해지하여도 동의하기가 가능합니다. 이렇게되면 저희는 필수정보인 이메일주소와 연령대를 제공받지 못합니다.

 

위점을 확인해주시고 계속 진행하겠습니다.

한경 추가를 클릭하여 PC웹으로 선택해주시고 서비스 URL (네이버로그인 호출 도메인)을 입력해주세요. 저희는 로컬에서 사용함으로 localhost를 적겠습니다. 그 후 네이버 로그인이 성공적으로 완료되면 저희가 받을 callback을 입력해주세요. Controller에서 RequsetMapping으로 URL 맵핑이 되어야합니다. 이렇게하시면 준비는 끝이납니다.


2. SDK 설정 및 화면 셋팅

<script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script>

CDN으로 사용하실분은 위에내용을 복붙해주세요.

만약 네이버 버튼의 디자인을 바꾸고싶으시다면 파일을 다운로드해주세요.

 

<span id="naver_id_login">
</span>
<script type="text/javascript" th:src="@{/resources/naver.js}"></script>
<script>
    naver_id_login.setButton("white", 2,40);
    naver_id_login.setPopup();
    naver_id_login.init_naver_id_login();
</script>

위 내용은 화면에서 네이버 로그인 버튼 코드입니다. 

 

네이버 API 키

var naver_id_login = new naver_id_login(naverKey, "http://localhost:8080/naver/login");
var state = naver_id_login.getUniqState();
naver_id_login.setDomain("http://localhost:8080");
naver_id_login.setState(state);

function naverLogin(response) {
	var data = { "accessToken" : response.oauthParams.access_token };
	// 엑세스 토큰 서버 전송
    
    
}

네이버.js 파일입니다. 엄청 짧죠? 당연히 Callback 화면도 있어야합니다.

Callback을 설명드리기전에! 네이버 버튼의 이미지를 바꾸고싶으시다면 아래의 접기를 봐주세요.

 

더보기

네이버 로그인 버튼 이미지 변경

이미지를 변경하고싶으시다면 naverLogin_implicit-1.0.3.js 파일을 수정하셔야합니다.

naver_id_login.setButton("white", 값, 40);

파일에서 검색을 해보시면 아래의 변수가 있습니다.

이변수들로 입력 받은 값과 일치하는 태그를 네이버 로그인 영역에 노출시킵니다.

BUTTON_TYPE = 1;
BANNER_SMALL_TYPE = 2;
BANNER_BIG_TYPE = 3;

 

 

if (this.button_type == BUTTON_TYPE)
{
    naver_id_login_contents="<a href='"+naver_id_login_url+"' "+naver_id_popup_option+" id='naver_id_login_anchor'><img src='이미지 경로' border='0' title='네이버 아이디로 로그인' width='폭' height='높이'></a> ";
}
else if (this.button_type == BANNER_SMALL_TYPE)
{
    naver_id_login_contents="<a href='"+naver_id_login_url+"' "+naver_id_popup_option+" id='naver_id_login_anchor'><img src='이미지 경로' border='0' title='네이버 아이디로 로그인' width='폭' height='높이'></a> ";
}
.......

naverLogin_implicit-1.0.3.js 파일에서 if문을 태우고 해당하는 이미지 경로와 크기를 입력해주시면 알맞게 변경됩니다.

 


Controller에 GetMapping을 하나 추가해주세요.

/**
 * 네이버 로그인 Call Back
 * */
@GetMapping("/naver/login")
public String callback() {
	return "/callback";
}

CallBack을 받기위한 맵핑입니다.

 

<html xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout">
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.3.min.js"></script>
<script type="text/javascript" src="https://static.nid.naver.com/js/naverLogin_implicit-1.0.3.js" charset="utf-8"></script>
<th:block layout:fragment="script">
	<script th:inline="javascript">
		var naver_id_login = new naver_id_login(naverKey, "http://localhost:8080/naver/login");
	    opener.parent.naverLogin(naver_id_login);
	    self.close();
	</script>
</th:block>

callback.html 에서는 부모의 naverLogin함수를 호출하여 response를 전달후 팝업창을 닫아버립니다. 

naverLogin함수에서 ajax를 통해 서버로 accessToken을 전달해주시면됩니다.


3. 서버에서 API를 통한 AccessToken 검증

 

먼저 dependency를 추가해주세요.

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.5</version>
</dependency>
public class NaverUtil {

	/**
	 * 네이버 Access Token 으로 회원정보 조회
	 * */
	public static HashMap<String, Object> getUserInfo (String accesstoken) {
		HashMap<String, Object> userInfo = new HashMap<>();
		String header = "Bearer " + accesstoken; // Bearer 다음에 공백 추가
		String apiURL = "https://openapi.naver.com/v1/nid/me";
		try {
			Map<String, String> requestHeaders = new HashMap<>();
			requestHeaders.put("Authorization", header);
			String responseBody = get(apiURL,requestHeaders);
			JsonParser parser = new JsonParser();
			JsonElement element = parser.parse(responseBody);
			JsonElement response = element.getAsJsonObject().get("response");

			String id = response.getAsJsonObject().get("id").getAsString();
			String email = response.getAsJsonObject().get("email").getAsString();
			String mobile = response.getAsJsonObject().get("mobile").getAsString();
			String name = response.getAsJsonObject().get("name").getAsString();
			String birthday = response.getAsJsonObject().get("birthday").getAsString();
			String year = response.getAsJsonObject().get("birthyear").getAsString();

			userInfo.put("id", id);
			userInfo.put("name", name);
			userInfo.put("email", email);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			return null;
		}
		return userInfo;
	}

	private static String get(String apiUrl, Map<String, String> requestHeaders){
		HttpURLConnection con = connect(apiUrl);
		try {
			con.setRequestMethod("GET");
			for(Map.Entry<String, String> header :requestHeaders.entrySet()) {
				con.setRequestProperty(header.getKey(), header.getValue());
			}


			int responseCode = con.getResponseCode();
			if (responseCode == HttpURLConnection.HTTP_OK) { // 정상 호출
				return readBody(con.getInputStream());
			} else { // 에러 발생
				return readBody(con.getErrorStream());
			}
		} catch (IOException e) {
			throw new RuntimeException("API 요청과 응답 실패", e);
		} finally {
			con.disconnect();
		}
	}

	private static HttpURLConnection connect(String apiUrl){
		try {
			URL url = new URL(apiUrl);
			return (HttpURLConnection)url.openConnection();
		} catch (MalformedURLException e) {
			throw new RuntimeException("API URL이 잘못되었습니다. : " + apiUrl, e);
		} catch (IOException e) {
			throw new RuntimeException("연결이 실패했습니다. : " + apiUrl, e);
		}
	}

	private static String readBody(InputStream body){
		InputStreamReader streamReader = new InputStreamReader(body);
		try (BufferedReader lineReader = new BufferedReader(streamReader)) {
			StringBuilder responseBody = new StringBuilder();
			String line;
			while ((line = lineReader.readLine()) != null) {
				responseBody.append(line);
			}
			return responseBody.toString();
		} catch (IOException e) {
			throw new RuntimeException("API 응답을 읽는데 실패했습니다.", e);
		}
	}
}

실제 호출할때는 getUserInfo를 호출하여 유저정보를 HashMap으로 return받을수있습니다.

return null이 들어올경우 accesstoken이 유효하지 않는 경우입니다.

 

서버측에서도 액세스토큰으로 정상적이 유저정보가 입력이되었다면 유저정보 기반으로 회원가입, 로그인을 진행하시면됩니다. 특히 간편로그인 회원가입의 경우 비밀번호를 입력받으면 반려사유가 될수있음으로 조심해주세요.

유저의 아이디는 NaverUtil.java에서 엑세스토큰으로 조회된 ID가 고유함으로 회원 ID로 사용하시면됩니다.

 

질문이나 글에서 수정, 추가됐으면 좋겠다는 부분이있으면 댓글적어주시면 빠르게 반영하겠습니다.

 

'IT > 기타' 카테고리의 다른 글

네이버와 연결된 서비스 관리  (0) 2022.02.22
윈도우 10 다크모드, 야간모드  (0) 2022.02.20
카카오 로그인 API  (0) 2022.02.16