API 시작 가이드 개요

네이버 클라우드 플랫폼 API 시작 가이드 개요에 대해서 설명합니다.

네이버 클라우드 플랫폼 API 시작 가이드 개요

자세한 내용은 네이버 클라우드 플랫폼 보안 API reference를 참고합니다.
해당 가이드에서는 간단한 시나리오를 통해, App Safer 감시 중인 앱에 대한 일별 통계 정보를 조회해보도록 합니다.
기술된 시나리오를 따라 해 봄으로써 보안 API에 대한 사용법을 익힐 수 있습니다.

시나리오 설명

소유하고 있는 앱에 대한 App Safer 감시 일별 통계 정보를 조회해 봅니다.
해당 시나리오는 App Safer 서비스에서 제공하는 SDK를 개발한 앱에 적용해야 볼 수 있는 통계 정보입니다.

앱에 대한 통계 정보 조회

특정 기간에 대한 앱의 일별 감시 통계 정보를 조회해 봅니다.

인증

해당 가이드에서는 시나리오 수행을 위한 인증 URL을 만드는 과정을 살펴 보도록 합니다.
Java 샘플코드로 작성되었고, GET 방식의 http request method를 사용하여 요청하는 방식으로 작성되었습니다.
실제 요청 시에는 GET 방식으로 요청하는 것보다 POST 방식으로 request body에 값을 넣어서 요청하는 것을 추천합니다.

인증 URL 생성

인증키를 생성하기 위해서 아래와 같은 절차를 따릅니다.

base string 생성

  1. 액션파라미터에 base string 생성에 필요한 인증 파라미터를 추가
  2. 요청파라미터와 value 값을 알파벳 순으로 정렬
  3. base string = RequestMethod + '&' + oauthEncode(requestUrl) + '&' + oauthEncode(queryString)

서명서 생성

Secret Key와 위에서 생성한 baseString을 가지고 HMAC SHA-1 해시알고리즘을 이용하여 서명서를 생성합니다.

요청 URL 생성

서명서까지 생성이 완료되었으면, 요청URL을 생성하여, API를 요청합니다.
OAuth 외부 라이브러리를 이용하여, authorization 헤더에 authparams 포함하여 쉽게 요청할 수도 있습니다.
자세한 사항은 OAuth 인증 가이드를 참고하기 바랍니다.

요청 URL 생성 java sample code

아래는 요청 URL을 생성하는 java sample code입니다.
해당 코드는 commons-codec-1.4.jar 라이브러리에 dependency를 가진다. 따라서 아래 코드를 수행하기 위해서는 해당 jar가 자신의 build path에 추가되어야 합니다.
해당 jar는 간단하게 google.com이나 naver.com에서 검색하여 다운로드할 수도 있고, 또는 네이버 클라우드 비즈 라이브러리에서 dependency 항목으로 함께 제공됩니다.

import java.io.UnsupportedEncodingException;import java.net.MalformedURLException;import java.net.URL;import java.net.URLEncoder;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.util.ArrayList;import java.util.Arrays;import java.util.BitSet;import java.util.HashMap;import java.util.Iterator;import java.util.List;import java.util.Map;import java.util.Random;import java.util.SortedMap;import java.util.SortedSet;import java.util.TreeMap;import java.util.TreeSet;import javax.crypto.Mac;import javax.crypto.spec.SecretKeySpec;import org.apache.commons.codec.DecoderException;import org.apache.commons.codec.binary.Base64;import org.apache.commons.codec.net.URLCodec;public class OAuthMain {    private static String consumerKey = "CCe2T0ilv4aO3kIevT3x";    private static String consumerSecret = "UXbllHzrAVV7rmcE270sESJZa3Fh8I2kOiBTf0oE";    public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {String requestMethod = "GET";String requestUrl = "https://api.ncloud.com";String nameSpace = "/security/";Map<String, List<String>> requestParameters = new HashMap<String, List<String>>();requestParameters.put("action", Arrays.asList("getAppInstanceStatistics"));requestParameters.put("appInstanceNo", Arrays.asList("314450"));requestParameters.put("startDate", Arrays.asList("20160622"));requestParameters.put("endDate", Arrays.asList("20160622"));requestParameters.put("responseFormatType", Arrays.asList("xml"));SortedMap<String, SortedSet<String>> significantParameters = getSignificateParametersForSiganturBaseString(requestParameters, consumerKey);String signatureBaseString = makeSignatureBaseString(requestMethod, requestUrl + nameSpace, significantParameters);String signature = sign(signatureBaseString, consumerSecret);String requestFullUrl = makeRequestUrl(requestUrl + nameSpace, significantParameters, signature);System.out.println(requestFullUrl);}    /**     * signature base string을 만들기 위한 significateParameter 설정     * @param requestParameters     * @param consumerKey     * @return     */    private static SortedMap<String, SortedSet<String>> getSignificateParametersForSiganturBaseString(Map<String, List<String>> requestParameters, String consumerKey) {        SortedMap<String, SortedSet<String>> significateParameters = convertTypeToSortedMap(requestParameters);        SortedSet<String> consumerKeySet = new TreeSet<String>();        consumerKeySet.add(consumerKey);        significateParameters.put("oauth_consumer_key", consumerKeySet);        SortedSet<String> nonceSet = new TreeSet<String>();        nonceSet.add(generateNonce());        significateParameters.put("oauth_nonce", nonceSet);        SortedSet<String> signatureMethodSet = new TreeSet<String>();        signatureMethodSet.add("HMAC-SHA1");        significateParameters.put("oauth_signature_method", signatureMethodSet);        SortedSet<String> timestampSet = new TreeSet<String>();        timestampSet.add(generateTimestamp());        significateParameters.put("oauth_timestamp", timestampSet);        SortedSet<String> versionSet = new TreeSet<String>();        versionSet.add("1.0");        significateParameters.put("oauth_version", versionSet);        return significateParameters;    }    /**     * @param requestParameters     * @param significateParameters     */    private static SortedMap<String, SortedSet<String>> convertTypeToSortedMap(Map<String, List<String>> requestParameters) {        SortedMap<String, SortedSet<String>> significateParameters = new TreeMap<String, SortedSet<String>>();        Iterator<String> parameterNames = requestParameters.keySet().iterator();        while (parameterNames.hasNext()) {            String parameterName = (String)parameterNames.next();            List<String> parameterValues = requestParameters.get(parameterName);            if (parameterValues == null) {                parameterValues = new ArrayList<String>();            }            for (String parameterValue : parameterValues) {                if (parameterValue == null) {                    parameterValue = "";                }                SortedSet<String> significantValues = significateParameters.get(parameterName);                if (significantValues == null) {                    significantValues = new TreeSet<String>();                    significateParameters.put(parameterName, significantValues);                }                significantValues.add(parameterValue);            }        }        return significateParameters;    }    /**     * @param url     * @return     */    private static String normalizeUrl(String url) {        try {            URL requestURL = new URL(url);            StringBuilder normalized = new StringBuilder(requestURL.getProtocol().toLowerCase()).append("://").append(requestURL.getHost().toLowerCase());            if ((requestURL.getPort() >= 0) && (requestURL.getPort() != requestURL.getDefaultPort())) {                normalized.append(":").append(requestURL.getPort());            }            normalized.append(requestURL.getPath());            return normalized.toString();        } catch (MalformedURLException e) {            throw new IllegalStateException("Illegal URL for calculating the OAuth signature.", e);        }    }    private static String generateTimestamp() {        return Long.toString(System.currentTimeMillis() / 1000L);    }    private static String generateNonce() {        return Long.toString((new Random()).nextLong());    }    /**     * base string 생성     * @param requestMethod     * @param requestUrl     * @param significantParameters     * @return     */    private static String makeSignatureBaseString(String requestMethod, String requestUrl, SortedMap<String, SortedSet<String>> significantParameters) {        StringBuilder queryString = getRequestQueryString(significantParameters);        requestUrl = normalizeUrl(requestUrl);        requestUrl = OAuthCodec2.oauthEncode(requestUrl);        return new StringBuilder(requestMethod.toUpperCase()).append('&').append(requestUrl).append('&').append(OAuthCodec2.oauthEncode(queryString.toString())).toString();    }    /**     * query string 생성     * @param significantParameters     * @return     */    private static StringBuilder getRequestQueryString(SortedMap<String, SortedSet<String>> significantParameters) {        StringBuilder queryString = new StringBuilder();        Iterator<Map.Entry<String, SortedSet<String>>> paramIt = significantParameters.entrySet().iterator();        while (paramIt.hasNext()) {            Map.Entry<String, SortedSet<String>> sortedParameter = paramIt.next();            Iterator<String> valueIt = sortedParameter.getValue().iterator();            while (valueIt.hasNext()) {                String parameterValue = valueIt.next();                queryString.append(OAuthCodec2.oauthEncode(sortedParameter.getKey())).append('=').append(OAuthCodec2.oauthEncode(parameterValue));                if (paramIt.hasNext() || valueIt.hasNext()) {                    queryString.append('&');                }            }        }        return queryString;    }    /**     * base string과 consumer secret key를 가지고 signature 생성     * @param signatureBaseString     * @param consumerSecret     * @return     * @throws NoSuchAlgorithmException     * @throws UnsupportedEncodingException     * @throws InvalidKeyException     */    private static String sign(String signatureBaseString, String consumerSecret) throws NoSuchAlgorithmException, UnsupportedEncodingException, InvalidKeyException {        Mac mac = Mac.getInstance("HmacSHA1");        SecretKeySpec spec = new SecretKeySpec(new String(consumerSecret + "&").getBytes("UTF-8"), "HmacSHA1");        mac.init(spec);        byte text[] = signatureBaseString.getBytes("UTF-8");        byte signatureBytes[] = mac.doFinal(text);        signatureBytes = Base64.encodeBase64(signatureBytes);        String signature = new String(signatureBytes, "UTF-8");        return signature;    }    /**     * request URL 생성     * @param requestParameters     * @param signature     * @return     * @throws UnsupportedEncodingException     */    private static String makeRequestUrl(String requestUrl, SortedMap<String, SortedSet<String>> significantParameters, String signature) throws UnsupportedEncodingException {        StringBuilder queryString = getRequestQueryString(significantParameters);        queryString.append('&').append("oauth_signature").append("=").append(URLEncoder.encode(signature, "UTF-8"));        return new StringBuffer(requestUrl).append("?").append(queryString.toString()).toString();    }}class OAuthCodec2 extends URLCodec {    private OAuthCodec2() {    }    public static String oauthEncode(String value) {        if (value == null)            return "";        try {            return new String(URLCodec.encodeUrl(SAFE_CHARACTERS, value.getBytes("UTF-8")), "US-ASCII");        } catch (UnsupportedEncodingException e) {            throw new RuntimeException(e);        }    }    public static String oauthDecode(String value) throws DecoderException {        if (value == null)            return "";        try {            return new String(URLCodec.decodeUrl(value.getBytes("US-ASCII")), "UTF-8");        } catch (UnsupportedEncodingException e) {            throw new RuntimeException(e);        }    }    protected static final BitSet SAFE_CHARACTERS;    static {        SAFE_CHARACTERS = (BitSet)URLCodec.WWW_FORM_URL.clone();        SAFE_CHARACTERS.clear(42);        SAFE_CHARACTERS.clear(32);        SAFE_CHARACTERS.set(126);    }}

main 메소드를 수행하면, 인증URL이 포함된 아래와 같은 요청URL을 볼 수 있습니다.

http://api.ncloud.com/security/?action=getAppInstanceStatistics&appInstanceNo=314450&approachKey=KGY88eHCdIx3JwS4nMix&endDate=20160622&oauth_consumer_key=KGY88eHCdIx3JwS4nMix&oauth_nonce=6096567817549598157&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1490242069&oauth_version=1.0&responseFormatType=xml&secretKey=GcGwamDzTd4t2yVh8cFR9HhzcDERDfwmCSo78BWs&startDate=20160622&oauth_signature=kfTEwpMzibOlQeNCJzXQxBnoXp0%3D

사용자는 마이페이지 > API 인증키 관리 화면에서 Access Key, Secret Key를 발급받고, 위의 예제에서 consumerKey, consumerSecret 값을 해당 값으로 변경 후 테스트 해야 합니다.

App Safer 통계 데이터의 경우 namespace가 /security/,으로 사용되니 참고 부탁드리며, 해당 URL복사하여 브라우저로 요청을 해봅시다.
아래와 같은 결과를 볼 수 있습니다.

시나리오 수행

시나리오 수행방법을 언급합니다.
모든 시나리오는 인증의 샘플코드 방식으로 설명되며, main 메소드의 파라미터 부분에 대해서만 설명합니다.

시나리오 수행

자신이 소유하고 있는 앱의 App Safer 통계 정보를 조회하기 위해서는 반드시 앱의 인스턴스 번호를 알아야 합니다. (앱의 인스턴스 번호는 콘솔의 상세보기에서 확인이 가능합니다.)

앱에 대한 통계 정보 조회

앞서 조회한 정보들을 이용해서 일정 기간 동안의 앱 감시 통계 정보를 조회해봅니다.

요청URL 생성
  1. 액션

    • getAppInstanceStatistics
  2. 액션파라미터

    • appInstanceNo : 314450
    • startDate : 20160622
    • endDate : 20160622

      public static void main(String[] args) throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException {
      String requestMethod = "GET";
      String requestUrl = "https://api.ncloud.com";
      String nameSpace = "/security/";
      Map<String, List<String>> requestParameters = new HashMap<String, List<String>>();
      requestParameters.put("action", Arrays.asList("getAppInstanceStatistics"));
      requestParameters.put("appInstanceNo", Arrays.asList("314450"));
      requestParameters.put("startDate", Arrays.asList("20160622"));
      requestParameters.put("endDate", Arrays.asList("20160622"));
      requestParameters.put("responseFormatType", Arrays.asList("xml"));
      SortedMap<String, SortedSet<String>> significantParameters = getSignificateParametersForSiganturBaseString(requestParameters, consumerKey);
      String signatureBaseString = makeSignatureBaseString(requestMethod, requestUrl + nameSpace, significantParameters);
      String signature = sign(signatureBaseString, consumerSecret);
      String requestFullUrl = makeRequestUrl(requestUrl + nameSpace, significantParameters, signature);
      System.out.println(requestFullUrl);
      }
      
URL 생성 결과
http://api.ncloud.com/security/?action=getAppInstanceStatistics&appInstanceNo=314450&approachKey=CCe2T0ilv4aO3kIevT3x&endDate=20160622&oauth_consumer_key=CCe2T0ilv4aO3kIevT3x&oauth_nonce=7429106142434256170&oauth_signature_method=HMAC-SHA1&oauth_timestamp=1469083237&oauth_version=1.0&responseFormatType=xml&secretKey=UXbllHzrAVV7rmcE270sESJZa3Fh8I2kOiBTf0oE&startDate=20160622&oauth_signature=IkMb0ETFxV1H7mPvrss9R9ochzc%3D
결과 수행

아래처럼 일정 기간 동안의 일별 감시통계 정보가 조회 됨을 확인할 수 있습니다.

연관 정보 바로가기

아래 가이드에서 연관 정보를 확인할 수 있습니다.

""에 대한 건이 검색되었습니다.

    ""에 대한 검색 결과가 없습니다.

    처리중...