hmac-auth プラグインは、HMAC アルゴリズムに基づいて HTTP リクエストの改ざんできない署名を生成し、その署名を ID 認証に使用します。
プラグインタイプ
認証と認可。
フィールド
認証設定
|
フィールド |
データ型 |
必須 |
デフォルト値 |
説明 |
|
consumers |
オブジェクトの配列 |
はい |
- |
サービスの呼び出し元です。リクエストの認証に使用します。 |
|
date_offset |
number |
いいえ |
- |
許容されるクライアント時刻オフセットの最大値です (秒)。システムは、リプレイ攻撃を防ぐために、 |
|
global_auth |
boolean |
いいえ (インスタンスレベルでの設定の場合にのみ必須) |
- |
インスタンスレベルのみ。true に設定すると、認証がグローバルに有効になります。false に設定すると、認証が設定済みのドメイン名とルートにのみ適用されます。未設定の場合、ドメイン名またはルートが設定されていないときに限り、認証がグローバルに有効になります。 |
consumers のフィールド:
|
フィールド |
データ型 |
必須 |
デフォルト値 |
説明 |
|
key |
string |
はい |
- |
コンシューマーのアクセスキーです。 |
|
secret |
string |
はい |
- |
署名の生成に使用するシークレットです。 |
|
name |
string |
はい |
- |
コンシューマーの名前です。 |
(オプション) 認可設定
|
フィールド |
データ型 |
必須 |
デフォルト値 |
説明 |
|
allow |
文字列の配列 |
いいえ (インスタンスレベル以外の設定の場合に必須) |
- |
ルートまたはドメイン名レベルでのみ設定できます。きめ細かい権限制御のために、一致したリクエストへのアクセスを許可するコンシューマーを指定します。 |
-
同一ルール内で、認可設定と認証設定を併用することはできません。
-
認証済みリクエストの場合、呼び出し元を識別するために
X-Mse-Consumerヘッダーが追加されます。
例
認証のグローバル設定とルートの認可設定
次の例では、特定のルートまたはドメインに対して hmac-auth 認証を有効にします。key フィールドは一意である必要があります。
次のプラグイン設定をインスタンスレベルで適用します:
global_auth: false
consumers:
- key: appKey-example-1
secret: appSecret-example-1
name: consumer-1
- key: appKey-example-2
secret: appSecret-example-2
name: consumer-2
次のプラグイン設定を route-a および route-b ルートに適用します:
allow:
- consumer-1
次のプラグイン設定を *.example.com および test.com ドメイン名に適用します:
allow:
- consumer-2
-
この例の
route-aおよびroute-bルートは、ゲートウェイルートの作成時に指定したルートです。クライアントリクエストがいずれかのルートに一致した場合、nameがconsumer-1の呼び出し元がゲートウェイにアクセスできます。それ以外の呼び出し元はゲートウェイにアクセスできません。 -
この例の
*.example.comおよびtest.comドメイン名は、リクエスト内のドメイン名の照合に使用します。クライアントリクエストがいずれかのドメイン名に一致した場合、nameがconsumer-2の呼び出し元がゲートウェイにアクセスできます。それ以外の呼び出し元はゲートウェイにアクセスできません。
グローバル認証の設定
global_auth: true
consumers:
- key: appKey-example-1
secret: appSecret-example-1
name: consumer-1
- key: appKey-example-2
secret: appSecret-example-2
name: consumer-2
署名メカニズム
設定の準備
署名の生成と検証のために、次の認証情報を設定します:
-
key:リクエストヘッダーx-ca-keyで使用します。 -
secret:リクエスト署名の生成に使用します。
クライアントでの署名生成
プロセス
クライアントは、次の手順で署名を生成します:
-
元のリクエストからキーとなるデータを抽出して、署名文字列を生成します。
-
設定した
secretで署名文字列を暗号化し、署名を生成します。 -
署名に関連するすべてのヘッダーを、元の HTTP リクエストに追加します。
署名文字列の抽出
クライアントは HTTP リクエストからキーとなるデータを抽出し、次の形式で署名文字列に結合します:
HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters
これらのフィールドは \n で区切ります。Headers フィールドが空の場合は \n は不要です。それ以外の空のフィールドについては、\n を保持する必要があります。署名は大文字と小文字を区別します。
各フィールドの抽出ルール:
-
HTTPMethod:POST などの HTTP メソッドです。大文字である必要があります。
-
Accept:Accept リクエストヘッダーの値です。空にできます。一部の HTTP クライアントはデフォルトで
*/*を設定し、署名検証の失敗原因となるため、Accept ヘッダーを明示的に設定することを推奨します。 -
Content-MD5:Content-MD5 ヘッダーの値です。空にできます。リクエストにフォーム以外のボディが含まれる場合にのみ計算されます。Java の例は次のとおりです:
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getBytes("UTF-8"))); -
Content-Type:Content-Type ヘッダーの値です。空にできます。
-
Date:時刻オフセット検証に使用する Date ヘッダーの値です。
date_offsetが設定されていない場合は空にできます。 -
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 + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
-
クエリおよびフォームパラメーターのキーはアルファベット順に並べ替えたうえで、上記のとおりに連結します。
-
クエリおよびフォームパラメーターが空の場合は、署名情報を追加せずにパスのみを使用します。
-
同じキーで値が異なる配列パラメーターの場合、署名計算には最初の値のみが使用されます。
署名文字列抽出の例
初期 HTTP リクエスト:
POST /http2test/test?param1=test HTTP/1.1
host:api.alibabacloud.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=taro&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=taro
署名の計算
署名文字列を生成した後、クライアントはそれを暗号化してエンコードし、最終的な署名を生成します。
このコードでは、stringToSign が抽出した署名文字列、secret がプラグイン設定のシークレット、sign が最終的な署名です。
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] secretBytes = secret.getBytes("UTF-8");
hmacSha256.init(new SecretKeySpec(secretBytes, 0, secretBytes.length, "HmacSHA256"));
byte[] result = hmacSha256.doFinal(stringToSign.getBytes("UTF-8"));
String sign = Base64.encodeBase64String(result);
stringToSign は UTF-8 バイト配列にエンコードされ、HMAC アルゴリズムで暗号化された後、Base64 エンコードされて署名が生成されます。
署名の追加
署名検証のために、Cloud-native API Gateway に送信するリクエストには次のヘッダーを含めます:
-
x-ca-key:設定した
keyです。必須です。 -
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.alibabacloud.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=taro&password=123456789
サーバー側での署名検証
プロセス
サーバーは、次の手順でクライアント署名を検証します:
-
リクエストからキーとなるデータを抽出して、署名文字列を取得します。
-
リクエストから
keyを読み取り、対応するsecretを検索します。 -
secretで署名文字列を暗号化し、署名を生成します。 -
サーバー側の署名と、リクエスト内のクライアント側署名を比較します。
署名エラーのトラブルシューティング
署名検証に失敗した場合、サーバーはサーバー側の StringToSign を X-Ca-Error-Message レスポンスヘッダーで返します。クライアント側の StringToSign と比較して差分を特定してください。
2 つの値が一致する場合は、署名計算に使用した secret を確認してください。
HTTP ヘッダーは改行をサポートしないため、StringToSign 内の改行は # に置き換えられます。
X-Ca-Error-Message: Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`
エラーコード
|
HTTP ステータスコード |
エラーメッセージ |
理由 |
|
400 |
Invalid Signature. |
x-ca-signature の署名が、サーバーで計算された署名と一致しません。 |
|
400 |
Invalid Content-MD5. |
Content-MD5 リクエストヘッダーが無効です。 |
|
400 |
Invalid Date. |
Date リクエストヘッダーの時刻オフセットが、設定された date_offset を超えています。 |
|
401 |
Invalid Key. |
x-ca-key リクエストヘッダーが欠落しているか、無効です。 |
|
401 |
Empty Signature. |
x-ca-signature リクエストヘッダーが空です。 |
|
403 |
Unauthorized Consumer. |
リクエストの呼び出し元にアクセス権限がありません。 |
|
413 |
Request Body Too Large. |
リクエストボディが 32 MB を超えています。 |
|
413 |
Payload Too Large. |
リクエストボディが、ゲートウェイに設定された |
DownstreamConnectionBufferLimits を増やすと、ゲートウェイのメモリ使用量が大幅に増加します。慎重に実施してください。