[배포시] 네이버 로그인 api 사용하기

Yeoonnii·2022년 11월 28일
1

Project

목록 보기
6/6

프로젝트 진행시 개발환경에서 네이버 로그인 api를 구현하였다

구현시 CORS에러를 해결하기 위해 아래와 같이 proxy를 설정하여 진행하였는데,
배포시 설정한 프록시가 적용되지 않는 문제가 생겼다


개발환경(Local)에서 proxy 설정

vue.config.js

  devServer : {
    proxy : {
... 
      '^/oauth2.0' : { 
        'target' : 'https://nid.naver.com/',
        'changeOringin' : true,
        'pathRewrite': { '^/oauth2.0': '/' },
        'secure':false
      },
      '^/v1' : {
        'target' : 'https://openapi.naver.com/',
        'pathRewrite' : { '^/v1': '/' },
        'changeOringin' : true,
        'secure':false,
        'logLevel' : 'debug'
      },
    },
    port : 9090
...

배포시 proxy 설정을 대체하는 법

proxy 설정은 개발환경(Local)에서만 적용되며 배포시에는 적용되지 않는다고 한다!
참고링크 - [TIL] 네이버 로그인 | CORS 에러 해결

해결 방법

  1. middleware를 설치하여 Proxy server를 생성해 해결하는 방법
  2. CORS 에러를 프론트에서 해결하여 프론트 단에서 처리
  3. 콜백 URI를 백엔드 단에서 처리 후 받아온 reponse 데이터를 다시 프론트로 리턴해주는 방법

네이버 권장 해결 방법

네이버에서는 백엔드 서버를 사용하여 API를 호출하는 방식을 권장
⇒ 네이버에서 권장하는 방법으로 문제를 해결해보았다


배포시 네이버 로그인 api 적용하기

pom 라이브러리 설치

  • OkHttp ⇒ REST API, HTTP 통신을 간편하게 구현할 수 있는 Java 라이브러리
  • OkioOkHttp를 기반으로 하는 컴팩트한 IO 라이브러리
  • org.json ⇒ Java의 JSON 라이브러리
	<dependency>
    	<groupId>com.squareup.okhttp</groupId>
    	<artifactId>okhttp</artifactId>
    	<version>2.7.5</version>
	</dependency>

	<dependency>
	    <groupId>com.squareup.okio</groupId>
	    <artifactId>okio</artifactId>
	    <version>1.6.0</version>
	</dependency>
	
	<!-- json -->
	<dependency>
		<groupId>org.json</groupId>
		<artifactId>json</artifactId>
		<version>20211205</version>
	</dependency>

API 호출을 위한 RestController

ApiLoginRestController.java

import java.util.HashMap;
import java.util.Map;

import org.json.JSONObject;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;
import com.squareup.okhttp.ResponseBody;


@RestController
@RequestMapping(value = "/api/login")
public class ApiLoginRestController {

	// 1. 접근 토큰 발급 요청 : Callback으로 전달받은 정보를 이용하여 접근 토큰을 발급받기
	// 콜백페이지(LoginNCallback.vue)에서 호출한다
	// 127.0.0.1:8080/fligent/api/login/oauth2.0?clientid=&code=&state=&secret=
	@GetMapping(value = "/oauth2.0")
	public Map<String, Object> oauth20(
		@RequestParam(name="clientid") String clientid,
		@RequestParam(name="code") String code,
		@RequestParam(name="state") String state,
		@RequestParam(name="secret") String secret){
		Map<String, Object> retMap = new HashMap<>();
		try {
	        String url = "https://nid.naver.com/oauth2.0/token?" 
	        		+ "grant_type=authorization_code&client_id=" + clientid
	        		+ "&client_secret=" + secret
					+ "&code=" + code
					+ "&state=" + state;

	        // OkHttp 클라이언트 객체 생성
	        OkHttpClient client = new OkHttpClient();
	 
	        // GET 요청 객체 생성
	        Request.Builder builder = new Request.Builder().url(url).get();
	        builder.addHeader("X-Naver-Client-Id", clientid);
	        builder.addHeader("X-Naver-Client-Secret", secret);
	        
	        Request request = builder.build();
	 
	        Response response = client.newCall(request).execute();
	        if (response.isSuccessful()) {
	            // 응답 받아서 처리
	            ResponseBody body = response.body();
	            // body.close();
	            if (body != null) {
	            	String str = body.string();
	            	retMap.put("status", 200);
	            	// retMap.put("result", body.string());
	                System.out.println("oauth20 의 Response  ==> " + str);
	                
                    // JSON 파싱
	                JSONObject jobj = new JSONObject(str);
	                retMap.put("access_token" , jobj.getString("access_token"));
	                retMap.put("refresh_token" , jobj.getString("refresh_token"));
	                retMap.put("token_type" , jobj.getString("token_type"));
	                retMap.put("expires_in" , jobj.getString("expires_in"));
	                
	                body.close();
	            }
	        }
	        else {
	            System.err.println("Error Occurred");
	        }

	    } catch(Exception e) {
	    	retMap.put("status", -1);
	        e.printStackTrace();
	    }
        return retMap;
	}
	
    
    
    // 2. 발급받은 토큰으로 사용자 정보 받아오기
	// 127.0.0.1:8080/fligent/api/login/v1?token=&
	@GetMapping(value = "/v1")
	public Map<String, Object> v1(@RequestParam(name="token") String token) {
		Map<String, Object> retMap = new HashMap<>();
		Map<String, Object> responseMap = new HashMap<>();
		try {
			System.out.println("param으로 받아온 access_token => " + token);
	        String url = "https://openapi.naver.com/v1/nid/me";
	          
	        // OkHttp 클라이언트 객체 생성
	        OkHttpClient client = new OkHttpClient();
	 
	        // GET 요청 객체 생성
	        Request.Builder builder = new Request.Builder().url(url).get();
	        builder.addHeader("Authorization", "Bearer " + token);
	        
	        Request request = builder.build();
	 
	        Response response = client.newCall(request).execute();
	        if (response.isSuccessful()) {
	            // 응답 받아서 처리
	            ResponseBody body = response.body();
	            if (body != null) {
	            	String str = body.string();
	            	body.close();

	                System.out.println("Response ==> " + str);

					// JSON 파싱
					JSONObject jobj = new JSONObject(str);
					JSONObject responseObj = jobj.getJSONObject("response");
	                responseMap.put("birthday" , responseObj.getString("birthday"));
	                responseMap.put("profile_image" , responseObj.getString("profile_image"));
	                responseMap.put("birthyear" , responseObj.getString("birthyear"));
	                responseMap.put("nickname" , responseObj.getString("nickname"));
	                responseMap.put("mobile" , responseObj.getString("mobile"));
	                responseMap.put("email" , responseObj.getString("email"));

					retMap.put("status", 200);
	                retMap.put("response" , responseMap);
                    
                    System.out.println("result ==> "+ responseMap.toString());
	            }
	        }
	        else {
	            System.err.println("Error Occurred");
	        }

	    } catch(Exception e) {
	        e.printStackTrace();
	    }
        return retMap;
	}
}

로직 정리 / 요청 결과

1. 접근 토큰 발급 요청

1-1. Vue 에서 callback uri로 받아온 code와 state를 백엔드로 보낸다
1-2. OkHttp를 이용하여 Callback으로 전달받은 'code' 값을 담아 '접근토큰발급API'를 호출한다
1-3. 받아온 결과를 파싱하여 vue로 결과를 리턴해준다

네이버 개발자센터 - 3.4.4 접근 토큰 발급 요청

2. 발급받은 토큰으로 사용자 정보 받아오기

2-1. OkHttp를 이용하여 발급 받은 접근 토큰을 담아 프로필 정보 조회 API를 호출한다.
2-2. 받아온 결과를 파싱하여 vue로 결과를 리턴해준다

네이버 개발자센터 - 3.4.5 접근 토큰을 이용하여 프로필 API 호출하기



참고링크

1개의 댓글

comment-user-thumbnail
2024년 4월 1일

안녕하세요~ 같은 내용 배포 연습 중에 있습니다.
혹시 백엔드에서 CORS 처리를 하게 되면, 프론트단의 proxy server는 설정이 불필요할까요?
그게 아니라면 백, 프론트 둘 다 처리 진행되어야 할까요?

답글 달기