サーバー構築不要!スマートフォンアプリ向けの新クラウド

トップ >ドキュメント >REST API リファレンス:シグネチャの生成方法

共通ドキュメント

シグネチャの生成方法

APIリクエスト時のシグネチャについて

REST APIをリクエストする際、シグネチャによる認証を行っています。

データストアでのオブジェクト検索APIのリクエストを例に、シグネチャの生成方法について説明します。
TestClassにて、testKeyがtestValueとなっているオブジェクトを検索します。
curlコマンドは以下のようになります。

curl -X GET -G \
 -H "X-NCMB-Application-Key:6145f91061916580c742f806bab67649d10f45920246ff459404c46f00ff3e56"\
 -H "X-NCMB-Timestamp:2013-12-02T02:44:35.452Z"\
 -H "X-NCMB-Signature:AltGkQgXurEV7u0qMd+87ud7BKuueldoCjaMgVc9Bes="\
 -H "Content-Type: application/json"\
 --data-urlencode 'where={"testKey":"testValue"}'\
 https://mbaas.api.nifcloud.com/2013-09-01/classes/TestClass

署名用文字列の生成

サンプルリクエストから以下の情報を取得して署名用の文字列を作成します。

リクエストメソッドを取得

オブジェクト検索はGETメソッドを利用するので、この場合GETとなります。

GET

FQDNを取得

APIリクエスト時のFQDNは以下のとおりです。

mbaas.api.nifcloud.com

リクエストしたAPIのパスを取得

REST APIリファレンスに記載されているAPIパスの前に、APIのバージョン「/2013-09-01」を合わせて
以下のように設定します。

/2013-09-01/classes/TestClass

クエリストリングの取得

各パラメータのキーと値は、URLエンコードされた状態で利用します。

where=%7B%22testKey%22%3A%22testValue%22%7D

アプリケーションキーを設定

管理画面のアプリ設定を開き、アプリケーションキーをコピーしてください。
X-NCMB-Application-Keyというキー名にマッピングします。

X-NCMB-Application-Key=6145f91061916580c742f806bab67649d10f45920246ff459404c46f00ff3e56

シグネチャメソッドを設定

mobile backendのREST APIでは、シグネチャ生成時にHmacSHA256のアルゴリズムを用いてハッシュ文字列を生成するので、
シグネチャメソッド "HmacSHA256" をキー名 SignatureMethod にマッピングします。

SignatureMethod=HmacSHA256

シグネチャバージョンを設定

mobile backendのREST APIでは、シグネチャバージョンに「2」を設定しますので、
キー名 SignatureVersion に"2"をマッピングします。

SignatureVersion=2

タイムスタンプを設定

現在時刻(UTC)を ISO8601 の形式で取得し、キー名 X-NCMB-Timestamp にマッピングします。

X-NCMB-Timestamp=2013-12-02T02:44:35.452Z

それぞれの値を「&」で連結

以下の5項目を、キーの自然順序付け・昇順で並び替えて「&」で連結します。

  • アプリケーションキー
  • シグネチャメソッド
  • シグネチャバージョン
  • タイムスタンプ
  • クエリストリング
SignatureMethod=HmacSHA256&SignatureVersion=2&X-NCMB-Application-Key=6145f91061916580c742f806bab67649d10f45920246ff459404c46f00ff3e56&X-NCMB-Timestamp=2013-12-02T02:44:35.452Z&where=%7B%22testKey%22%3A%22testValue%22%7D

署名用文字列の作成

以下の4つを改行「\n」で連結することで、署名用文字列の生成を行います。

  • リクエストメソッド
  • FQDN
  • APIパス
  • 「&」で連結された文字列
GET\n
mbaas.api.nifcloud.com\n
/2013-09-01/classes/TestClass\n
SignatureMethod=HmacSHA256&SignatureVersion=2&X-NCMB-Application-Key=6145f91061916580c742f806bab67649d10f45920246ff459404c46f00ff3e56&X-NCMB-Timestamp=2013-12-02T02:44:35.452Z&where=%7B%22testKey%22%3A%22testValue%22%7D

署名用文字列を元にシグネチャを生成

署名用文字列をメッセージ、クライアントキーを秘密鍵としてHmacSHA256でエンコードし、
それをBase64でエンコードしたものが、シグネチャとなります。

クライアントキーを以下のものに設定し、本ページに書かれているサンプルリクエストの
アプリケーションキー・タイムスタンプを設定したうえで、
同じシグネチャが作成されるかを確認してみてください。

# クライアントキー
1343d198b510a0315db1c03f3aa0e32418b7a743f8e4b47cbff670601345cf75

# 作成されるシグネチャ
AltGkQgXurEV7u0qMd+87ud7BKuueldoCjaMgVc9Bes=

リクエストへのシグネチャ付加

リクエストヘッダーにシグネチャ(X-NCMB-Signature)、タイムスタンプ(X-NCMB-Timestamp)、
アプリケーションキー(X-NCMB-Application-Key)を付加してリクエストを送信します。
タイムスタンプ(X-NCMB-Timestamp)、アプリケーションキー(X-NCMB-Application-Key)はシグネチャの生成に用いたものをそのまま使用します。
最終的なリクエストは冒頭に記載したもののようになります。

curl -X GET -G \
 -H "X-NCMB-Application-Key:6145f91061916580c742f806bab67649d10f45920246ff459404c46f00ff3e56"\
 -H "X-NCMB-Timestamp:2013-12-02T02:44:35.452Z"\
 -H "X-NCMB-Signature:AltGkQgXurEV7u0qMd+87ud7BKuueldoCjaMgVc9Bes="\
 -H "Content-Type: application/json"\
 --data-urlencode 'where={"testKey":"testValue"}'\
 https://mbaas.api.nifcloud.com/2013-09-01/classes/TestClass

APIのレスポンスからシグネチャの検証を行う

APIのレスポンス時には、ヘッダーにあるシグネチャと
レスポンスデータから作成するシグネチャが一致しているか
検証を行うことで、データの改ざん有無を確認することができます。

レスポンスシグネチャの作成手順はリクエスト時とほぼ同じです。
ただし、シグネチャを生成する前の署名用文字列に
レスポンスデータ(バイナリデータは16進数形式の文字列に変換したもの)
を追加する必要があります。

Javaのシグネチャ作成サンプルコード

        private static final String APPLICATIONKEY = "YOUR APPLICATION KEY";
        private static final String CLIENTKEY = "YOUR CLIENT KEY";

        public static void main(String[] args) throws Exception {
            String baseURL = "https://mbaas.api.nifcloud.com/2013-09-01/classes/TestClass";
            String query = "{\"testKey\":\"testValue\"}";

            String encodedQuery = URLEncoder.encode(query.toString(),"UTF-8");
            URIBuilder uriBuilder = new URIBuilder(baseURL);
            uriBuilder.addParameter("where",encodedQuery);
            //シグネチャ生成メソッド呼び出し
            String signature = getSignature("GET" ,uriBuilder.build() , APPLICATIONKEY, CLIENTKEY);
            //生成されるシグネチャ出力
            System.out.println(signature);
        }

    private String getSignature(String requestMethod, URI uri, String applicationKey, String clientKey) throws Exception{
        //タイムスタンプを取得
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        String _timestamp = df.format(new Date());

        //SignatureMethod,SignatureVersion,X-NCMB-Application-Key,X-NCMB-Timestampをパラメータに追加
        URIBuilder _uri = new URIBuilder(uri);
        _uri.addParameter("SignatureMethod", "HmacSHA256")
            .addParameter("SignatureVersion", "2")
            .addParameter("X-NCMB-Application-Key", applicationKey)
            .addParameter("X-NCMB-Timestamp", _timestamp);

        //パラメータをソート
        List<NameValuePair> params = _uri.getQueryParams();
        Collections.sort(params, new Comparator<NameValuePair>() {
            @Override
            public int compare(NameValuePair o1, NameValuePair o2) {
                return o1.getName().compareTo(o2.getName());
            }
        });

        //パラメータを連結
        StringBuilder sortedQuery = new StringBuilder(256);
        for (NameValuePair param : params) {
            sortedQuery.append(param.getName()).append('=').append(param.getValue()).append('&');
        }
        sortedQuery.deleteCharAt(sortedQuery.lastIndexOf("&"));

        //署名用文字列を生成
        StringBuilder sign = new StringBuilder(256);
        sign.append(requestMethod.toUpperCase()).append('\n')
            .append(uri.getHost()).append('\n')
            .append(uri.getRawPath()).append('\n')
            .append(sortedQuery);

        //シグネチャを生成
        Mac mac = Mac.getInstance("HmacSHA256");
        mac.init(new SecretKeySpec(clientKey.getBytes("UTF-8"), "HmacSHA256"));
        return Base64.encodeBase64String(mac.doFinal(sign.toString().getBytes("UTF-8")));
    }

Objective-Cのシグネチャ作成サンプルコード

// NSDictionaryをソートした文字列へ変換
-(NSString*)concatenateQuery:(NSDictionary*)parameters {
    if(!parameters||[parameters count]==0) return nil;
    NSMutableString *query = [NSMutableString string];
    NSArray *sortedKeys = [[parameters allKeys] sortedArrayUsingSelector:@selector(compare:)];
    for(NSString *key in sortedKeys)
        [query appendFormat:@"&%@=%@",key,parameters[key]];
    return [query substringFromIndex:1];
}

// key=value形式のNSStringを辞書へ変換
-(NSDictionary*)splitQuery:(NSString*)query {
    if(!query||[query length]==0) return nil;
    NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
    for(NSString *parameter in [query componentsSeparatedByString:@"&"]) {
        NSRange range = [parameter rangeOfString:@"="];

        NSString *value,*key;
        if(range.location!=NSNotFound){
            value = [parameter substringFromIndex:range.location+range.length];
            key = [parameter substringToIndex:range.location];
        }else{
            value = [parameter substringFromIndex:range.length];
            key = [[NSString new] autorelease];
        }

        parameters[key] = value;
    }
    return parameters;
}

-(NSString*)makeHashMapWithTimeStamp:(NSString*)timeStamp AppKey:(NSString*)appKey clientkey:(NSString*)clientKey{

    // hash map の生成
    NSMutableDictionary *hashMap = [NSMutableDictionary dictionaryWithCapacity:0];
    hashMap[SIGNATURE_METHOD] = signatureMethod;
    hashMap[SIGNATURE_VERSION] = signatureVersion;
    hashMap[XNCMB_APPLICATIONKEY] = appKey;
    hashMap[XNCMB_TIMESTAMP] =  timeStamp;

    // query stringの追加
    NSString *queryString = nil;
    NSDictionary* queryDic= nil;

    if([[self HTTPMethod] isEqualToString:@"GET"]){

        queryString = [[self URL] query];
        NSLog(@"queryString  %@",queryString);
        queryDic = [self splitQuery:queryString];

    }
    for (NSString *key in [queryDic allKeys]) {
        hashMap[key] = queryDic[key];
    }
    NSString *sortedHashMapStr = [self concatenateQuery:hashMap];
    NSLog(@"hash Map:%@",hashMap);

    NSLog(@"sortedHashMapStr %@",sortedHashMapStr);
    return sortedHashMapStr;
}
-(NSString *)makeSignature:(NSString*)data secretKey:(NSString *)secret {

    NSString *str = @"";

    //署名作成
    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

    const char *cKey = [secret cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];

    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    //署名を付加したRESTリクエスト作成
    NSData *HMAC = [[[NSData alloc]initWithBytes:cHMAC length:sizeof(cHMAC)] autorelease];

    // encodeなし
    str = [HMAC stringEncodedWithBase64];

    return str;
}

JavaScriptのシグネチャ作成サンプルコード

  NCMB._createSignature = function(route, className, objectId, url, method, timestamp){
    var signature = "";
    var _applicationKey = NCMB.applicationKey;
    var _timestamp = timestamp;
    var _clientKey = NCMB.clientKey;

    var _method = method;
    var _url = encodeURI(url);
    var _tmp = _url.substring(_url.lastIndexOf("//") + 2);
    var _fqdn = _tmp.substring(0, _tmp.indexOf("/"));  

    var _position = _url.indexOf("?");
    var _path = "";
    var _data = {};

    if(_position == -1) {
      _path =  _url.substring(_url.lastIndexOf(_fqdn) + _fqdn.length );
    }
    else{
      var _get_parameter= _url.substring(_position + 1);
      _path = _url.substring(_url.lastIndexOf(_fqdn) + _fqdn.length, _position);
      _tmp = _get_parameter.split("&");
      for (var i = 0; i < _tmp.length; i++) {
      _position = _tmp[i].indexOf("=");
      _data[_tmp[i].substring(0 , _position)] = _tmp[i].substring(_position + 1);
      }
    }
    _data["SignatureMethod"] = "HmacSHA256";
    _data["SignatureVersion"] = "2";
    _data["X-NCMB-Application-Key"] = _applicationKey;
    _data["X-NCMB-Timestamp"] = _timestamp;

    var _sorted_data = {};
    var keys = [];
    var k, i, len;
    for (k in _data)
    {
      if (_data.hasOwnProperty(k))
      {
        keys.push(k);
      }
    }
    keys.sort();
    len = keys.length;
    for (i = 0; i < len; i++)
    {
      k = keys[i];
      _sorted_data[k] = _data[k];
    }
    var parameterString = "";
    for (k in _sorted_data)
    {
      if (_sorted_data.hasOwnProperty(k))
      {
        if (parameterString != "") {
          parameterString += "&";
        };
        parameterString = parameterString + k + "=" + _sorted_data[k];
      }
    }
    var forEncodeString = _method + "\n" + _fqdn + "\n" + _path + "\n" + parameterString;
    var hash = CryptoJS.HmacSHA256(forEncodeString, _clientKey);
    var signature = CryptoJS.enc.Base64.stringify(hash);                 
    return signature;
  }

お探しの内容が見つからなかった場合はユーザーコミュニティ もご活用ください。(回答保証はいたしかねます)
なお、 Expertプラン以上のお客様はテクニカルサポートにてご質問を承らせて頂きます。

推奨画面サイズ1024×768px以上

ページの先頭へ