기본적인 OAuth의 1.0과 2.0에 대한 정보

+) NAVER에서 사용하고 있는 내용



참고 문서(링크)

(1) NAVER D2 사이트 내의 OAuth에 대한 탄생과 사용 및 1.0과 2.0 소개

: https://d2.naver.com/helloworld/24942


(2) NAVER CLOUD PALTFORM 사이트 내의 OAuth 이용 가이드.

: https://docs.ncloud.com/ko/storage/storage-2-3.html



- 상세 내용

(1) 출처 : https://d2.naver.com/helloworld/24942

개요

네이버 클라우드 플랫폼과 네이버 클라우드 플랫폼 API를 정의하고, 네이버 클라우드 플랫폼 API 인증 방식인 OAuth 인증 방식을 소개합니다.

네이버 클라우드 플랫폼과 네이버 클라우드 플랫폼 API

네이버 클라우드 플랫폼은 NAVER의 최신 컴퓨팅 기술과 운영 노하우가 축적된 클라우드 서비스입니다. 네이버 클라우드 플랫폼에서 제공하는 여러 가지 상품군 중에 솔루션 상품을 이용할 수 있도록 제공하는 응용 프로그램 인터페이스(API)를 네이버 클라우드 플랫폼 API라고 합니다.

네이버 클라우드 플랫폼 API는 표준화된 OAuth 인증을 이용합니다. OAuth 인증 방식은 별도의 시스템이 로그인 정보를 저장하지 않도록 하고 암호화된 인증 토큰을 이용해야만 리소스에 접근할 수 있도록 허용하므로 안전합니다. 또한 다양한 플랫폼의 오픈 라이브러리(OAuth Client Library)를 사용할 수 있도록 지원합니다. 네이버 클라우드 플랫폼에서 제공하는 API는 이러한 OAuth 인증 방식의 통일된 체계를 통해 인증을 처리합니다.

OAuth 인증 방식

기존의 애플리케이션이나 웹 서비스에서는 아이디와 비밀번호를 사용하여 사용자 인증을 수행합니다. 이러한 인증 방식은 애플리케이션을 제작하거나 웹 서비스를 운영하는 회사마다 서로 다른 방법으로 사용자를 확인합니다. 하지만 표준화된 OAuth 인증 방식을 이용하면 해당 인증을 공유하는 애플리케이션이나 웹 서비스 사이에 별도의 인증이 필요 없어 개발자 입장에서는 더 간편하게 인증 절차를 구현할 수 있습니다.

3-legged OAuth 인증 방식

OAuth 인증 방식은 전형적으로 3 party system (User, Consumer, Service Provider) 형태로 고안되어 있습니다. 이러한 방식을 3-legged 인증 방식이라고 합니다.

  • User: Service Provider에 계정을 가진 사용자
  • Consumer: User를 대신하여 Service Provider에 접근하기 위해 OAuth를 사용하는 웹 서비스나 애플리케이션
  • Service Provider: OAuth를 통해 접근을 허용하는 웹 애플리케이션

2-legged OAuth 인증 방식

네이버 클라우드 플랫폼 API에서는 Consumer와 Service Provider가 동일하므로, 3-legged 인증 방식보다 간소화된 2-legged 인증 방식을 지원하고 있습니다.

즉, 3 party system 구조에서 Consumer가 생략되었다고 보면 됩니다. 2-legged OAuth 인증 방식의 흐름은 다음과 같습니다.

네이버 클라우드 플랫폼 API에서 사용하는 OAuth 버전은 OAuth 1.0a(http://tools.ietf.org/html/rfc5849)를 기반으로 합니다.

네이버 클라우드 플랫폼 API 인증 절차

OAuth 인증 방식을 적용해 네이버 클라우드 플랫폼 API를 사용하는 방법을 설명합니다.

네이버 클라우드 플랫폼 API 사용 절차

네이버 클라우드 플랫폼 API를 사용하려면 다음과 같은 과정을 거쳐야 합니다.

  • API 인증키 발급(생략 가능)
  • API URL 검증(생략 가능)
  • OAuth 인증 클라이언트 구현

API 인증키는 기본으로 발급되며 API URL 검증도 편의를 위해 제공되는 부분이므로 생략할 수 있습니다.

API 인증키 발급

네이버 클라우드 플랫폼 계정이 생성되면 기본적으로 네이버 클라우드 플랫폼 API 인증키가 하나 발급됩니다. 발급된 인증키는 네이버 클라우드 플랫폼 포털 웹사이트 로그인 후 마이페이지 > API 인증키 관리에서 확인할 수 있습니다.

인증키는 계정 생성 시 자동으로 발급되는 것 외에 사용자가 하나 더 생성할 수 있어서 두 개까지 발급받을 수 있습니다. 인증키를 사용 안 함으로 설정하거나 삭제하면 유효하지 않은 키로 인식됩니다.

API 인증키는 Access Key와 Secret Key 한 쌍으로 구성되어 있습니다. Access Key는 API를 인증할 때 파라미터로 직접 전달되며, Secret Key는 OAuth_signature 파라미터를 서명할 때 사용합니다.

API URL 검증

OAuth 인증 시 OAuth 파라미터를 전달하는 방식은 2가지입니다. HTTP 호출 시 GET 방식으로 URL 자체에 OAuth 인증에 필요한 파라미터를 붙여서 전달하는 방식과 HTTP 헤더에 넣어서 보내는 방식이 있습니다.

구분설명
목적API를 사용하기 위해 네이버 클라우드 플랫폼 사이트에서 얻어야 할 정보를 확인할 수 있습니다. 
API 인증키 값의 유효성을 확인할 수 있습니다. 
API 동작 여부와 결과를 확인할 수 있습니다.
UI 확인값URL 기능 동작 대상 URL(예: 컨테이너명/파일명) 
API URL (GET) 
http://restapi.fs.ncloud.com{URL}? 
&oauth_consumer_key={Access Key} 
&oauth_timestamp={timestamp} 
&oauth_signature={oauth signature} 
&oauth_nonce={nonce 값} 
&oauth_signature_method=HMAC-SHA1 
&oauth_version=1.0 
예) 
http://restapi.fs.ncloud.com/{컨테이너명}? 
{해당기능} 
&oauth_consumer_key={Access Key} 
&oauth_timestamp={timestamp} 
&oauth_signature={oauth signature} 
&oauth_nonce={nonce 값} 
&oauth_signature_method=HMAC-SHA1 
&oauth_version=1.0
입력값인증 Access Key 선택(예: xoiOTgN2sgjDb5oRzp8q).
인증 Secret Key(인증 Access Key 선택에 따라 자동으로 선택됨).
(예: SMSyGbEi7ucZpPnRGlomftWRNENz0TV1mMOI7MiA)
* 실제 API 사용 시 인증 Access Key와 인증 Secret Key를 사용해 인증 파라미터('oauth_'를 prefix로 사용하는 파라미터)를 생성하여 request에 추가하는데, URL 검증하기 기능을 통해 그 정보들의 구성 예를 확인할 수 있습니다.

서비스 서버에 적용되는 URL과 파라미터 관련 내용은 다음 절에서 설명합니다.

OAuth 인증 클라이언트 구현

네이버 클라우드 플랫폼 API를 사용하려면 아래 표에 명시된 URL과 필수 파라미터를 생성하여 요청해야 합니다.

구분필요 여부인자 설명
호출 URLY호출 대상 기능 URL. 형식은 http://restapi.fs.ncloud.com/{기능요청URL}?{파라미터}이다. 
예) http://restapi.fs.ncloud.com/{test}?list...
인증 파라미터YOAuth 인증을 위한 파라미터이며, 이 정보들은 header에 구성할 수 있습니다. 
oauth_consumer_key 
예) oauth_consumer_key=xoiOTgN2sgjDb5oRzp8q 
oauth_signature_method 
예) oauth_signature_method=HMAC-SHA1 
oauth_version 
예) oauth_version=1.0 
oauth_timestamp 
예) oauth_timestamp=1335419436 
oauth_nonce 
예) oauth_nonce=W4SkWT 
oauth_signature 
예) oauth_signature=qVsXa0Pf913BIhv55f06ont3aIE%3D

아래 3가지로 분류하여 소개합니다.

  • 인증 파라미터 생성 방법
  • 서명서(signature) 생성 절차 및 예제(자바)
  • 오픈 라이브러리를 이용한 인증 파라미터 생성

인증 파라미터 생성 방법

네이버 클라우드 플랫폼 API는 표준 OAuth를 지원하므로 다양한 오픈 Client Library를 사용하여 인증 파라미터를 생성할 수 있습니다.
생성된 인증 파라미터는 앞 절의 URL 예시처럼 HTTP Request에 파라미터로 추가하거나 헤더에 추가하여 사용할 수 있습니다.

구분설명
oauth_consumer_key마이페이지 > API 인증키 관리에서 생성한 Access Key 값. 
예) oauth_consumer_key=xoiOTgN2sgjDb5oRzp8q
oauth_signature_methodOAuth 서명 방식. 고정값으로 HMAC-SHA1를 사용합니다. 
예) oauth_signature_method=HMAC-SHA1
oauth_versionOAuth 버전. 고정값으로 1.0을 사용합니다. 
예) oauth_version=1.0
oauth_timestamptimestamp 값. 오픈 라이브러리를 사용할 수 있으며, 사용 예제는 "오픈 라이브러리를 이용한 인증 파라미터 생성“ 절을 참조합니다. 
예) oauth_timestamp=1335419436
oauth_nonce재전송 공격(replay attack)에 대한 예방으로 재사용 방지를 위한 일회성 파라미터입니다. 오픈 라이브러리를 사용할 수 있으며, 사용 예제는 "오픈 라이브러리를 이용한 인증 파라미터 생성“ 절을 참조합니다. 
예) oauth_nonce=W4SkWT
oauth_signature마이페이지 > API 인증키 관리에서 생성한 Secret Key를 사용한 서명이다(일회성). oauth_consumer_key와 쌍을 이룬 Secret Key여야 합니다. 
오픈 라이브러리를 사용할 수 있으며, 사용 예제는 "오픈 라이브러리를 이용한 인증 파라미터 생성" 절을 참고합니다. 
예) oauth_signature=qVsXa0Pf913BIhv55f06ont3aIE%3D

서명서(signature) 생성 절차 및 예제(자바)

서명서(signature)생성을 위한 절차를 기술합니다.

  • baseString 생성
  • signature 생성
  • 요청 URL 생성(queryString 방식 또는 Authorization Header 방식)

baseString 생성

  1. 요청 파라미터에 baseString 생성에 필요한 파라미터를 추가합니다.
  2. 요청 파라미터와 value 값을 알파벳순으로 정렬합니다.
  3. baseString = RequestMethod + '&' + oauthEncode(requestUrl) + '&' + oauthEncode(queryString)

java 예제)

  • 요청 파라미터에 baseString 생성에 필요한 파라미터를 추가합니다.
  • 요청 파라미터와 value 값을 알파벳순으로 정렬합니다.
  • 파라미터 넣는 부분은 API에서 받는 파라미터가 존재할 때만 넣습니다.

  • 예제 코드에서 사용자가 값을 변경해야 할 부분은 아래와 같습니다.

    • String consumerKey = "consumer-k1";
    • String consumerSecret = "consumer-secret1";
    • String requestUrl = " http://restapi.fs.ncloud.com/container/resource ";
    • String requestMethod = "GET";
    • requestParameters.put("list", null);
    • requestParameters.put("test_param1", Arrays.asList("a"));
    • requestParameters.put("test_param2", Arrays.asList("b2", "b1"));
    • requestParameters.put("test_param3", Arrays.asList("한글"));
    /**
     * signature base string을 만들기 위한 significantParameter 세팅
     * @param requestParameters
     * @param consumerKey
     * @return
     */
    private SortedMap<String, SortedSet<String>> getSignificantParametersForSignaturBaseString(Map<String, List<String>> requestParameters, String consumerKey) {
        SortedMap<String, SortedSet<String>> significantParameters = convertTypeToSortedMap(requestParameters);

        SortedSet<String> consumerKeySet = new TreeSet<String>();
        consumerKeySet.add(consumerKey);
        significantParameters.put("oauth_consumer_key", consumerKeySet);

        SortedSet<String> nonceSet = new TreeSet<String>();
        nonceSet.add(generateNonce());
        significantParameters.put("oauth_nonce", nonceSet);

        SortedSet<String> signatureMethodSet = new TreeSet<String>();
        signatureMethodSet.add("HMAC-SHA1");
        significantParameters.put("oauth_signature_method", signatureMethodSet);

        SortedSet<String> timestampSet = new TreeSet<String>();
        timestampSet.add(generateTimestamp());
        significantParameters.put("oauth_timestamp", timestampSet);

        SortedSet<String> versionSet = new TreeSet<String>();
        versionSet.add("1.0");
        significantParameters.put("oauth_version", versionSet);

        System.out.println("significantParameters : " + significantParameters);

        return significantParameters;
    }

    /**
     *
     * @param requestParameters
     * @return
     */
    private SortedMap<String, SortedSet<String>> convertTypeToSortedMap(Map<String, List<String>> requestParameters) {
        SortedMap<String, SortedSet<String>> significantParameters = new TreeMap<String, SortedSet<String>>();

        Iterator<String> parameterNames = requestParameters.keySet().iterator();
        while (parameterNames.hasNext()) {
            String parameterName = parameterNames.next();

            if (requestParameters.get(parameterName) == null || requestParameters.get(parameterName).size() == 0) {
                SortedSet<String> significantValues = new TreeSet<String>();
                significantValues.add("");
                significantParameters.put(parameterName, significantValues);
            } else {
                for (String parameterValue : requestParameters.get(parameterName)) {
                    if (parameterValue == null) {
                        parameterValue = "";
                    }

                    SortedSet<String> significantValues = significantParameters.get(parameterName);
                    if (significantValues == null) {
                        significantValues = new TreeSet<String>();
                        significantParameters.put(parameterName, significantValues);
                    }
                    significantValues.add(parameterValue);
                }
            }
        }
        return significantParameters;
    }

    private String generateTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000L);
    }

    private String generateNonce() {
        return Long.toString((new Random()).nextLong());
    }

a. baseString = RequestMethod + '&' + oauthEncode(requestUrl) + '&' + oauthEncode(queryString)

    /**
     * signature base string 생성을 위한 query string 생성
     * @param significantParameters
     * @return
     */
    private StringBuilder getQueryStringForBaseString(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(OAuthCodec.oauthEncode(sortedParameter.getKey())).append('=').append(OAuthCodec.oauthEncode(parameterValue));
                if (paramIt.hasNext() || valueIt.hasNext()) {
                    queryString.append('&');
                }
            }
        }
        return queryString;
    }

    /**
     * signature base string 생성
     * @param requestMethod
     * @param requestUrl
     * @param significantParameters
     * @return
     */
    private String makeSignatureBaseString(String requestMethod, String requestUrl, SortedMap<String, SortedSet<String>> significantParameters) {
        StringBuilder queryString = getQueryStringForBaseString(significantParameters);

        requestUrl = normalizeUrl(requestUrl);
        requestUrl = OAuthCodec.oauthEncode(requestUrl);

        return new StringBuilder(requestMethod.toUpperCase()).append('&').append(requestUrl).append('&').append(OAuthCodec.oauthEncode(queryString.toString())).toString();
    }

    /**
     * @param url
     * @return
     */
    private 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);
        }
    }

    class OAuthCodec extends URLCodec {

        private OAuthCodec() {
        }

        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);
        }
    }

signature 생성

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

java 예제)

    /**
     * base string과 consumer secret key를 가지고 signature 생성
     * @param signatureBaseString
     * @param consumerSecret
     * @return
     * @throws NoSuchAlgorithmException
     * @throws UnsupportedEncodingException
     * @throws InvalidKeyException
     */
    private 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");
        System.out.println("signature : " + signature);
        return signature;
    }

요청 URL 생성(queryString 방식 또는 Authorization Header 방식)

java 예제)

  • queryString 방식
    /**
     * request URL 생성을 위한 query string 생성
     * @param significantParameters
     * @return
     */
    private StringBuilder getQueryStringForRequest(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();
                if (StringUtils.isEmpty(parameterValue)) {
                    queryString.append(OAuthCodec.oauthEncode(sortedParameter.getKey()));
                } else {
                    queryString.append(OAuthCodec.oauthEncode(sortedParameter.getKey())).append('=').append(OAuthCodec.oauthEncode(parameterValue));
                }

                if (paramIt.hasNext() || valueIt.hasNext()) {
                    queryString.append('&');
                }
            }
        }
        return queryString;
    }

    /**
     * request URL 생성
     * @param requestUrl
     * @param significantParameters
     * @param signature
     * @return
     * @throws UnsupportedEncodingException
     */
    private String makeRequestUrl(String requestUrl, SortedMap<String, SortedSet<String>> significantParameters, String signature) throws UnsupportedEncodingException {
        StringBuilder queryString = getQueryStringForRequest(significantParameters);
        queryString.append('&').append("oauth_signature").append("=").append(URLEncoder.encode(signature, "UTF-8"));
        return new StringBuffer(requestUrl).append("?").append(queryString.toString()).toString();
    }

    /**
     * queryString 방식 요청 수행
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public void request() throws IOException, NoSuchAlgorithmException, InvalidKeyException {

        String consumerKey = "consumer-k1";
        String consumerSecret = "consumer-secret1";
        String requestUrl = " http://restapi.fs.ncloud.com/container/resource";
        String requestMethod = "GET";
        Map<String, List<String>> requestParameters = new HashMap<String, List<String>>();
        requestParameters.put("list", null);
        requestParameters.put("test_param1", Arrays.asList("a"));
        requestParameters.put("test_param2", Arrays.asList("b2", "b1"));
        requestParameters.put("test_param3", Arrays.asList("한글"));

        SortedMap<String, SortedSet<String>> significantParameters = getSignificantParametersForSignaturBaseString(requestParameters, consumerKey);
        String baseString = makeSignatureBaseString(requestMethod, requestUrl, significantParameters);
        String signature = sign(baseString, consumerSecret);
        String signedUrl = makeRequestUrl(requestUrl, significantParameters, signature);
        System.out.println("signedUrl : " + signedUrl);

        URL obj = new URL(signedUrl);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod(requestMethod);

        int responseCode = con.getResponseCode();
        System.out.println("Response Code : " + responseCode);

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        System.out.println(response.toString());
    }
  • Authorization Header 방식
    /**
     * @param significantParameters
     * @param signature
     * @return
     * @throws UnsupportedEncodingException
     */
    private String makeAuthorizationHeader(SortedMap<String, SortedSet<String>> significantParameters, String signature) throws UnsupportedEncodingException {
        StringBuilder authorizationHeaderString = new StringBuilder();

        Iterator<Map.Entry<String, SortedSet<String>>> paramIt = significantParameters.entrySet().iterator();
        while (paramIt.hasNext()) {
            Map.Entry<String, SortedSet<String>> sortedParameter = paramIt.next();
            int valueSize = sortedParameter.getValue().size();
            Iterator<String> valueIt = sortedParameter.getValue().iterator();

            if ("oauth_consumer_key".equals(sortedParameter.getKey())) {
                if (valueSize != 1) {
                    throw new IllegalArgumentException("oauth_consumer_key is empty or one more value.");
                }
                authorizationHeaderString.append("oauth_consumer_key").append('=').append('\"').append(valueIt.next()).append('\"');
                authorizationHeaderString.append(", ");
            }

            if ("oauth_nonce".equals(sortedParameter.getKey())) {
                if (valueSize != 1) {
                    throw new IllegalArgumentException("oauth_nonce is empty or one more value.");
                }
                authorizationHeaderString.append("oauth_nonce").append('=').append('\"').append(valueIt.next()).append('\"');
                authorizationHeaderString.append(", ");
            }

            if ("oauth_signature_method".equals(sortedParameter.getKey())) {
                if (valueSize != 1) {
                    throw new IllegalArgumentException("oauth_signature_method is empty or one more value.");
                }
                authorizationHeaderString.append("oauth_signature_method").append('=').append('\"').append(valueIt.next()).append('\"');
                authorizationHeaderString.append(", ");
            }

            if ("oauth_timestamp".equals(sortedParameter.getKey())) {
                if (valueSize != 1) {
                    throw new IllegalArgumentException("oauth_timestamp is empty or one more value.");
                }
                authorizationHeaderString.append("oauth_timestamp").append('=').append('\"').append(valueIt.next()).append('\"');
                authorizationHeaderString.append(", ");
            }

            if ("oauth_version".equals(sortedParameter.getKey())) {
                if (valueSize != 1) {
                    throw new IllegalArgumentException("oauth_version is empty or one more value.");
                }
                authorizationHeaderString.append("oauth_version").append('=').append('\"').append(valueIt.next()).append('\"');
                authorizationHeaderString.append(", ");
            }
        }

        return new StringBuffer().append("OAuth ").append(authorizationHeaderString.toString()).append("oauth_signature").append('=').append('\"').append(URLEncoder.encode(signature, "UTF-8")).append('\"').toString();
    }

    /**
     * Authorization Header 방식 요청 수행
     * @throws IOException
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public void request2() throws IOException, NoSuchAlgorithmException, InvalidKeyException {
        String consumerKey = "consumer-k1";
        String consumerSecret = "consumer-secret1";
        String requestUrl = " http://restapi.fs.ncloud.com/container/resource";
        String requestMethod = "GET";
        Map<String, List<String>> requestParameters = new HashMap<String, List<String>>();
        requestParameters.put("list", null);
        requestParameters.put("test_param1", Arrays.asList("a"));
        requestParameters.put("test_param2", Arrays.asList("b2", "b1"));
        requestParameters.put("test_param3", Arrays.asList("한글"));

        SortedMap<String, SortedSet<String>> significantParameters = getSignificantParametersForSignaturBaseString(requestParameters, consumerKey);
        String baseString = makeSignatureBaseString(requestMethod, requestUrl, significantParameters);
        String signature = sign(baseString, consumerSecret);

        StringBuilder queryString = getQueryStringForRequest(convertTypeToSortedMap(requestParameters));
        requestUrl += "?" + queryString.toString();
        System.out.println("requestUrl : " + requestUrl);

        String authorizationHeaderValue = makeAuthorizationHeader(significantParameters, signature);
        System.out.println("authorizationHeaderValue : " + authorizationHeaderValue);

        URL obj = new URL(requestUrl);
        HttpURLConnection con = (HttpURLConnection) obj.openConnection();
        con.setRequestMethod(requestMethod);
        con.setRequestProperty("Authorization", authorizationHeaderValue);

        int responseCode = con.getResponseCode();
        System.out.println("response Code : " + responseCode);

        BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
        String inputLine;
        StringBuffer response = new StringBuffer();

        while ((inputLine = in.readLine()) != null) {
            response.append(inputLine);
        }
        in.close();

        System.out.println(response.toString());
    }

오픈 라이브러리를 이용한 인증 파라미터 생성

인증 파라미터를 생성할 때 오픈 라이브러리를 활용할 수 있습니다. 
이 예제에서는 signpost-core 라이브러리를 사용합니다. 
이 라이브러리를 사용하게 되면 헤더에 인증 파라미터가 붙어서 전달됩니다.

signpost-core 라이브러리를 직접 다운로드하거나, Maven을 사용한다면 pom.xml에 아래와 같이 설정합니다.

<dependency>
   <groupId>oauth.signpost</groupId>
   <artifactId>signpost-core</artifactId>
   <version>1.2</version>
   <scope>compile</scope>
</dependency>

다음의 예제 코드를 참고하여 OAuth 인증 파라미터를 포함한 HTTP 요청을 생성합니다.

  • 예제 코드에서 사용자가 값을 변경해야 할 부분은 아래와 같습니다.
    • String consumerKey = "consumer-k1";
    • String consumerSecret = "consumer-secret1";
    • String requestUrl = " http://restapi.fs.ncloud.com/container/resource";
    • String requestMethod = "GET";
    • requestParameters.put("list", null);
    • requestParameters.put("test_param1", "a");
    • requestParameters.put("test_param2", Arrays.asList("b2", "b1"));
    /**
     * 라이브러리 요청 수행
     * @throws IOException
     * @throws OAuthMessageSignerException
     * @throws OAuthExpectationFailedException
     * @throws OAuthCommunicationException
     */
    public void request() throws IOException, OAuthMessageSignerException, OAuthExpectationFailedException, OAuthCommunicationException {

        String consumerKey = "consumer-k1";
        String consumerSecret = "consumer-secret1";
        String requestUrl = " http://restapi.fs.ncloud.com/container/resource";
        String requestMethod = "GET";

        Map<String, Object> requestParameters = new HashMap<String, Object>();
        requestParameters.put("list", null);
        requestParameters.put("test_param1", "a");
        requestParameters.put("test_param2", Arrays.asList("b2", "b1"));

        StringBuffer queryString = new StringBuffer();
        int index= 1;
        int requestParamSize = requestParameters.size();
        for (String key : requestParameters.keySet()) {
            if (index == 1) {
                queryString.append("?");
            }
            queryString.append(key);

            if (requestParameters.get(key) != null) {
                queryString.append('=');
                queryString.append(URLEncoder.encode(requestParameters.get(key).toString(), "UTF-8"));
            }
            if (index!= requestParamSize) {
                queryString.append("&");
                index ++;
            }
        }

        OAuthConsumer consumer = new DefaultOAuthConsumer(consumerKey, consumerSecret);

        URL url = new URL(requestUrl + queryString.toString());
        HttpURLConnection con = (HttpURLConnection)url.openConnection();

        con.setRequestMethod(requestMethod);
        con.setConnectTimeout(500000);
        con.setUseCaches(false);
        con.setDefaultUseCaches(false);

        consumer.sign(con);

        con.connect();

        int responseCode = con.getResponseCode();
        System.out.println("ResponseCode : " + responseCode);

        if (responseCode == HttpURLConnection.HTTP_OK) {
            BufferedReader resultReader = new BufferedReader(new InputStreamReader(con.getInputStream(), "utf-8"));
            StringBuffer requestResult = new StringBuffer();
            String readString = null;
            while ((readString = resultReader.readLine()) != null) {
                requestResult.append(readString);
            }

            System.out.println(requestResult.toString());
        }
    }

부록. 약어/용어

약어 정리

OAuth     Open standard for Authorization

HMAC     Hash-based Message Authentication Code

SHA     Secure Hash Algorithm

연관 정보 바로가기

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


+ Recent posts