OAuth署名生成 python3実装サンプル

OAuth署名生成 python3実装サンプル

OAuth署名生成のpython3による実装サンプルを以下に示します。

# -*- coding: utf-8 -*-
#
### OAuth HMAC-SHA1方式の署名を作成する.
# @link https://support.e-map.ne.jp/manuals/v3?q=sig_implement_python3
# 
# make_signature_hmac(http_method, parameter, uri, secret)
# @param string http_method HTTPメソッドを指定
# @param dict parameter  クエリパラメータとOAuthパラメータをマージしたもの
# @param string uri   実際にリクエストするURI(リクエストパラメータは含めない)
# @param string secret   秘密鍵
#
### oauthパラメータ一覧
# oauth_consumer_key   ZDCから発行されたクライアントIDを設定します
# oauth_signature_method "HMAC-SHA1""HMAC-SHA256""HMAC-SHA3-256"のいずれかを設定します
# oauth_signature    リクエストURIより生成したOAuth署名を設定します。生成手順はマニュアルサイト「OAuth署名の作成手順」を参照ください
# oauth_timestamp    現在時刻のUNIXタイムスタンプを設定します
# oauth_nonce     リクエスト毎に一意なランダム値を設定します
# oauth_version    ”1.0” 固定

import time
import urllib.parse
import urllib
import urllib.request
import hmac
import hashlib
import base64

# 動作確認用
http_method = 'GET'
parameter = {
    'if_clientid'           : '', #キー
    'if_auth_type'          : 'oauth',
    'word'                  : '', #任意の検索語句
    'oauth_consumer_key'    : '', #キー
    'oauth_signature_method': 'HMAC-SHA1', #任意のアルゴリズム
    'oauth_timestamp'       : int(time.time()),
    'oauth_nonce'           : '', #任意の文字列
    'oauth_version'         : '1.0',
    'oauth_signature'       : ''
}
uri = 'http://core.its-mo.com/zmaps/api/apicore/core/v1_0/address/word' #使用するAPI
secret = '' # キーに紐づく秘密鍵

def make_signature_hmac(http_method, parameter, uri, secret):
    # http_method
    http_method = http_method.upper()
    # print('\n' + '***http_method***' + '\n' +http_method)
    
    # params
    if 'oauth_signature' in parameter:
        del parameter['oauth_signature']
    # Signature Base String生成処理中のURLエンコード時はRFC3986を使用するため、quote_viaにurllib.parse.quoteを指定する
    params = urllib.parse.urlencode(sorted(parameter.items(), key=lambda x: x[0]), quote_via=urllib.parse.quote)
    # print('\n' + '***params***' + '\n' +params)

    # uri
    parts = urllib.parse.urlparse(uri)
    scheme = parts.scheme if parts.scheme else 'http'
    port = parts.port or (443 if scheme == "https" else 80)
    host = parts.netloc
    path = parts.path or ""
    uri = f"{scheme}://{host}{path}"

    # secret
    # 秘密鍵は「指定したキー + &」の形式で記述すること
    secret += '&'

    # base_string
    # Signature Base String生成処理中のURLエンコード時はRFC3986を使用するため、urllib.parse.quoteを用いる
    base_string = f"{http_method}&{urllib.parse.quote(uri, '')}&{urllib.parse.quote(params, '')}"

    # oauth_signature
    # signatureはバイト型になる
    signature_method = parameter.get("oauth_signature_method", "HMAC-SHA1")
    hmac_algo = signature_method.replace("HMAC-", "").lower()
    digestmod = getattr(hashlib, hmac_algo, None)
    if digestmod is None:
        return None

    # base64エンコードを行う
    signature = hmac.new(secret.encode(), base_string.encode(), digestmod).digest()
    signature_encoded = base64.b64encode(signature).decode()
    parameter['oauth_signature'] = signature_encoded
    return signature_encoded

# 以下、動作確認用
make_signature_hmac(http_method, parameter, uri, secret)
url = uri + '?' + urllib.parse.urlencode(parameter)
print('\n' + '***URL***' + '\n' + url)

result = None
try :
    result = urllib.request.urlopen( url ).read()
    print('\n' + result.decode())
except ValueError :
    print('アクセスに失敗しました。')
except IOError :
    print('認証に失敗しました。')