ダイジェスト認証方式(AppKey と AppSecret)を使用する公開済み API を呼び出すには、クライアントは署名キーペアを使用してリクエストされたコンテンツの署名を計算し、その署名をサーバー側に送信して検証する必要があります。API Gateway SDK には署名メカニズムが付属しています。SDK で署名キーペアを設定した後、正しい署名を含むリクエストを開始できます。このトピックでは、クライアントで署名を計算する方法について説明します。
1. 概要
API Gateway は、署名生成と署名検証の機能を提供します。これらの機能は、以下のシナリオで使用されます。
クライアントから受信したリクエストの有効性をチェックし、リクエストに、承認された AppKey に基づいて生成された正しい署名が含まれていることを確認します。
転送中にリクエストが改ざんされるのを防ぎます。
API プロバイダーは、API Gateway コンソールの [アプリ] ページでアプリケーションを作成できます。各アプリケーションには、AppKey と AppSecret で構成される署名キーペアがあります。API プロバイダーがアプリケーションに API の呼び出しを承認すると、API 呼び出し側はアプリケーションと署名キーペアを使用して API を呼び出すことができます。アプリケーションは、API プロバイダーによって発行されるか、API 呼び出し側が所有するものであることに注意してください。
クライアントが API を呼び出すとき、クライアントは承認された署名キーペアを使用してリクエストを暗号化および署名し、AppKey と署名文字列をリクエストのヘッダーに追加してから、リクエストを API Gateway に送信する必要があります。API Gateway はリクエストを受信すると、リクエストヘッダーから AppKey を読み取り、AppKey に対応する AppSecret を取得します。次に、API Gateway は AppSecret を使用してリクエスト内のキーデータの署名を計算し、計算された署名をクライアントからの署名と比較して署名を検証します。署名検証に合格したリクエストのみがバックエンドサービスに送信されます。API Gateway がリクエストが無効であると判断した場合、API Gateway はエラーを返します。
API Gateway は、セキュリティ認証の値が Alibaba Cloud アプリである API のリクエストの署名のみを検証します。
2. SDK を使用した API 呼び出し
署名の計算方法の詳細については、API Gateway によって提供される SDK をご参照ください。API Gateway コンソールの次のページで、ソースコードが付属する Java、Android、Objective-C 用の SDK をダウンロードできます。
Open API > SDK
API の呼び出し > 承認済み API SDK
詳細については、「SDK を使用して API を呼び出す」をご参照ください。
3. ダイジェスト認証の原則
3.1. 署名の生成と検証
3.1.1. 前提条件
関連する API に割り当てられた署名キーペアは、API 呼び出し側が API を呼び出す前に取得します。
APP Key
APP Secret
呼び出される API のセキュリティ認証の値は Alibaba Cloud アプリです。
3.1.2. クライアントでの署名生成
署名を生成するには、クライアントは次の手順を実行する必要があります。
リクエストからキーデータを抽出して署名文字列を取得します。
暗号化アルゴリズムと AppSecret を使用して署名文字列を暗号化し、署名を取得します。
署名に関連するすべてのヘッダーを元の HTTP リクエストに追加して、最終的な HTTP リクエストを取得します。
3.1.3. サーバーでの署名検証
クライアントからの署名を検証するには、サーバーは次の手順を実行する必要があります。
受信したリクエストからキーデータを抽出して署名文字列を取得します。
リクエストから AppKey を読み取り、AppKey を使用して AppSecret を取得します。
暗号化アルゴリズムと AppSecret を使用して署名文字列を暗号化し、署名を取得します。
リクエストからクライアント側の署名を読み取り、サーバー側の署名とクライアント側の署名を比較します。
3.2. 署名の生成と転送
3.2.1. 署名文字列の抽出
クライアントは、HTTP リクエストからキーデータを抽出し、そのデータを署名文字列に結合する必要があります。署名文字列の形式は次のとおりです。
HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters上記のフィールドは署名文字列を構成し、\n で区切られます。Headers フィールドを空のままにする場合、\n は不要です。他のフィールドを空のままにする場合は、\n を保持する必要があります。署名は大文字と小文字を区別します。各フィールドのデータ抽出は、次のルールに従います。
HTTPMethod: リクエストの送信に使用される HTTP メソッド(例: POST)。このフィールドの値は大文字です。
Accept: リクエストの Accept ヘッダーの値。Accept ヘッダーは空のままにすることができます。リクエストで Accept ヘッダーを指定することをお勧めします。Accept ヘッダーが空のままの場合、特定の HTTP クライアントは Accept にデフォルト値 */* を使用します。この場合、署名検証は失敗します。
Content-MD5: Content-MD5 ヘッダーの値。空のままにすることができます。
値は、リクエストに Form タイプ以外の本文が含まれている場合にのみ計算されます。Content-MD5 がクライアントで計算されない場合、またはクライアントが API Gateway に渡さない場合、API Gateway は Content-MD5 を検証しません。
次の例は、Java で Content-MD5 ヘッダーの値を計算するために使用されます。
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));Content-Type: Content-Type ヘッダーの値。空のままにすることができます。
基盤となるロジック、またはクライアントがミニプログラムを使用して WeChat でファイルを転送する場合に、Content-Type の例外が発生する可能性があります。この場合、カスタム Content-Type ヘッダーとして X-Ca-Signed-Content-Type:multipart/form-data をリクエストに追加できます。クライアントがこのヘッダーを使用する場合、API Gateway もこのヘッダーを使用します。
Date: リクエストの Date ヘッダーの値。空のままにすることができます。
Headers: 署名の計算に使用するヘッダーを指定できます。署名文字列を連結する場合、次のルールが適用されます。
ヘッダーキーはアルファベット順にソートされ、次のルールに基づいて連結されます。
HeaderKey1 + ":" + HeaderValue1 + "\n" + HeaderKey2 + ":" + HeaderValue2 + "\n" + ... HeaderKeyN + ":" + HeaderValueN + "\n"ヘッダーの値が空の場合は、署名に HeaderKey + ":" + "\n" を使用し、ヘッダーキーとコロン(:)を保持します。
署名に使用されるヘッダーキーはコンマ(,)で区切られ、キーが X-Ca-Signature-Headers であるヘッダーに配置されます。
次のヘッダーを使用して署名を計算することはできません: X-Ca-Signature、X-Ca-Signature-Headers、Accept、Content-MD5、Content-Type、Date。
PathAndParameters フィールドには、Path、Query、Form の以下のすべてのタイプのパラメーターが含まれます。
Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueNQuery パラメーターと Form パラメーターのキーはアルファベット順にソートされ、上記のメソッドを使用して連結されます。
Query パラメーターと Form パラメーターを空のままにする場合は、疑問符(?)を追加せずに Path パラメーターを使用できます。
パラメーターが空のままの場合、キーのみが署名に使用されます。
Query パラメーターと Form パラメーターに、同じキーで異なる値を持つ配列パラメーターがある場合、最初の値が署名の計算に使用されます。
次の例は、標準 HTTP リクエストのパラメーターを示しています。
POST /http2test/test?param1=test HTTP/1.1
host:api.aliyun.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
content-length:33
username=xiaoming&password=123456789上記の例のリクエストに対して、次の署名文字列が生成されます。
POST
application/json; charset=utf-8
application/x-www-form-urlencoded; charset=utf-8
Wed, 09 May 2018 13:30:29 GMT+00:00
x-ca-key:203753385
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-signature-method:HmacSHA256
x-ca-timestamp:1525872629832
/http2test/test?param1=test&password=123456789&username=xiaoming3.2.2. 署名の計算
クライアントは、HTTP リクエストから抽出されたキーデータを署名文字列に結合した後、署名文字列を暗号化およびエンコードして最終的な署名を生成する必要があります。API Gateway は、次の暗号化アルゴリズムをサポートしています。
HmacSHA256
HmacSHA1
次の例は暗号化方法を示しています。ここで、stringToSign は抽出された署名文字列、secret は AppSecret です。
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] appSecretBytes = appSecret.getBytes(Charset.forName("UTF-8"));
hmacSha256.init(new SecretKeySpec(appSecretBytes, 0, appSecretBytes.length, "HmacSHA256"));
byte[] md5Result = hmacSha256.doFinal(stringToSign.getBytes(Charset.forName("UTF-8")));
String signature = Base64.encodeBase64String(md5Result);Mac hmacSha1 = Mac.getInstance("HmacSHA1");
byte[] appSecretBytes = appSecret.getBytes(Charset.forName("UTF-8"));
hmacSha1.init(new SecretKeySpec(appSecretBytes, 0, appSecretBytes.length, "HmacSHA1"));
byte[] md5Result = hmacSha1.doFinal(stringToSign.getBytes(Charset.forName("UTF-8")));
String signature = Base64.encodeBase64String(md5Result);StringToSign が UTF-8 でデコードされた後、バイト配列が取得されます。次に、バイト配列が暗号化され、Base64 でエンコードされて最終的な署名が生成されます。
3.2.3. 署名の転送
クライアントは、署名検証のために API Gateway に送信されるリクエストに、次のヘッダーの一部またはすべてを含める必要があります。
x-ca-key: AppKey。このパラメーターは必須です。
x-ca-signature-method: 署名メソッド。このパラメーターはオプションです。有効な値: HmacSHA256 と HmacSHA1。デフォルト値: HmacSHA256。
X-Ca-Signature-Headers: すべての署名ヘッダーのキー。このパラメーターはオプションです。複数のキーはコンマ(,)で区切ります。
X-Ca-Signature: 署名。このパラメーターは必須です。
次の例は、署名を持つ HTTP リクエストを示しています。
POST /http2test/test?param1=test HTTP/1.1
host:api.aliyun.com
accept:application/json; charset=utf-8
ca_version:1
content-type:application/x-www-form-urlencoded; charset=utf-8
x-ca-timestamp:1525872629832
date:Wed, 09 May 2018 13:30:29 GMT+00:00
user-agent:ALIYUN-ANDROID-DEMO
x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
x-ca-key:203753385
x-ca-signature-method:HmacSHA256
x-ca-signature-headers:x-ca-timestamp,x-ca-key,x-ca-nonce,x-ca-signature-method
x-ca-signature:xfX+bZxY2yl7EB/qdoDy9v/uscw3Nnj1pgoU+Bm6xdM=
content-length:33
username=xiaoming&password=1234567893.3. トラブルシューティング
署名検証が失敗した場合、API Gateway はサーバー側の署名文字列(StringToSign)をクライアントに返される HTTP 応答のヘッダーに追加します。キーは X-Ca-Error-Message です。クライアント側の署名文字列(StringToSign)とサーバー側の署名文字列を比較することで、エラーを特定できます。
2 つの値が同じ場合は、署名の計算に使用された AppSecret を確認してください。
HTTP ヘッダーは改行をサポートしていません。署名文字列(StringToSign)の改行は番号記号(#)に置き換えられます。
errorMessage: Invalid Signature, Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`次の例は、サーバー側の署名文字列を示しています。
GET
application/json
application/json
X-Ca-Key:200000
X-Ca-Timestamp:1589458000000
/app/v1/config/keys?keys=TEST