すべてのプロダクト
Search
ドキュメントセンター

API Gateway:ダイジェスト認証を使用してAPIを呼び出す

最終更新日:Jul 31, 2024

ダイジェスト認証方法 (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がリクエストを受信すると、API GatewayはリクエストヘッダーからAppKeyを読み取り、AppKeyに対応するAppSecretを取得します。 次に、API GatewayはAppSecretを使用してリクエスト内のキーデータの署名を計算し、計算された署名をクライアントからの署名と比較して署名を検証します。 署名検証に合格したリクエストのみがバックエンドサービスに送信されます。 API Gatewayがリクエストが無効であると判断した場合、API Gatewayはエラーを返します。

API Gatewayは、セキュリティ認証値がAlibaba Cloud AppであるAPIに対してのみ、リクエストの署名を検証します。

2. SDKを使用したAPI呼び出し

署名を計算する方法の詳細については、API Gatewayが提供するSDKを参照してください。 API Gatewayコンソールの次のページで、ソースコードに付属のJava、Android、およびObjective-C用のSDKをダウンロードできます。

  • オープンAPI > SDK

  • APIの呼び出し> 承認済みAPI SDK

詳細については、「」をご参照ください。

3. ダイジェスト認証の原理

3.1。 署名の生成と検証

3.1.1. 前提条件

関連するAPIに割り当てられた署名鍵ペアは、API呼び出し元がAPIを呼び出す前にAPI呼び出し元によって取得されます。

  • APPキー

  • アプリの秘密

呼び出されたAPIのセキュリティ認証値はAlibaba Cloud Appです。

3.1.2. クライアントでの署名生成

署名を生成するには、クライアントは次の手順を実行する必要があります。

  1. リクエストからキーデータを抽出して署名文字列を取得します。

  2. 暗号化アルゴリズムとAppSecretを使用して署名文字列を暗号化し、署名を取得します。

  3. 署名に関連するすべてのヘッダーを元のHTTPリクエストに追加して、最終的なHTTPリクエストを取得します。

3.1.3. サーバーでの署名検証

クライアントから署名を検証するには、サーバーは次の手順を実行する必要があります。

  1. 受信したリクエストからキーデータを抽出し、署名文字列を取得します。

  2. リクエストからAppKeyを読み取り、AppKeyを使用してAppSecretを取得します。

  3. 暗号化アルゴリズムとAppSecretを使用して署名文字列を暗号化し、署名を取得します。

  4. リクエストからクライアント側の署名を読み取り、サーバー側の署名をクライアント側の署名と比較します。

3.2。 署名の生成と転送

3.2.1. 署名文字列の抽出

クライアントは、HTTPリクエストからキーデータを抽出し、そのデータを署名文字列に結合する必要があります。 署名文字列の形式は次のとおりです。

HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters

上記のフィールドは署名文字列を構成し、\nで区切られます。 Headersフィールドを空のままにすると、\nは必要ありません。 他のフィールドを空のままにする場合は、\nを保持する必要があります。 署名は大文字と小文字を区別します。 各フィールドのデータ抽出は、次のルールに従います。

  • HTTPMethod: POSTなどのリクエストの送信に使用されるHTTPメソッド。 このフィールドの値は大文字です。

  • Accept: リクエスト内のAcceptヘッダーの値。 Acceptヘッダーは空のままにすることができます。 リクエストにAcceptヘッダーを指定することを推奨します。 Acceptヘッダーが空の場合、特定のHTTPクライアントはAcceptのデフォルト値 */* を使用します。 この場合、署名検証は失敗する。

  • Content-MD5: Content-MD5ヘッダーの値。空のままにすることができます。 この値は、リクエストにフォーム以外のタイプのボディが含まれている場合にのみ計算されます。 次の例は、Java形式のContent-MD5ヘッダーの値を計算するために使用されます。

String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));

  • Content-Type: Content-Typeヘッダーの値。空のままにすることができます。

重要

Content-Type例外は、基になるロジックが原因で、またはクライアントがWeChatでファイルを転送するためにミニプログラムを使用する場合に発生する可能性があります。 この場合、X-Ca-Signed-Content-Type:multipart/form-dataをカスタムContent-Typeヘッダーとしてリクエストに追加できます。 クライアントがこのヘッダーを使用する場合、API Gatewayもこのヘッダーを使用します。

  • Date: リクエスト内のDateヘッダーの値。空のままにすることができます。

  • ヘッダー: ヘッダーを指定して署名を計算できます。 署名文字列を連結すると、次のルールが適用されます。

    • ヘッダーキーはアルファベット順にソートされ、次のルールに基づいて連結されます。

    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 + "=" + ValueN
    • クエリおよびフォームパラメーターのキーはアルファベット順に並べ替えられ、上記の方法を使用して連結されます。

    • クエリパラメーターとフォームパラメーターを空のままにしておくと、疑問符 (?) を追加する必要なく、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=xiaoming

3.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でデコードされた後に取得されます。 次に、Byte配列をBase64で暗号化およびエンコードして、最終署名を生成します。

3.2.3. 署名転送

クライアントは、署名検証のためにAPI Gatewayに送信されるリクエストに次のヘッダーの一部またはすべてを含める必要があります。

  • x-ca-key: AppKey。 This parameter is required.

  • x-ca-signature-method: 署名方法。 このパラメーターはオプションです。 有効な値: HmacSHA256およびHmacSHA1 デフォルト値: HmacSHA256。

  • X-Ca-Signature-Headers: すべての署名ヘッダーのキー。 このパラメーターはオプションです。 複数のキーはコンマ (,) で区切ります。

  • X-Ca-Signature: 署名。 This parameter is required.

次の例は、署名を持つ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=123456789

3.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