バックエンド署名キーは、作成するキーとシークレットのペアです。このペアは API Gateway の認証情報として機能します。API にバックエンド署名プラグインをアタッチすると、API Gateway はこのキーとシークレットを使用して、バックエンドサービスに送信する前にリクエストに署名します。バックエンドサービスは、受信したリクエストに対して対称署名計算を実行できます。その署名をサーバー側で計算した署名と比較することで、ゲートウェイを認証できます。
1. バックエンド署名
バックエンド署名 (旧称:署名キー) は、作成するキーとシークレットのペアです。このペアは、ゲートウェイに発行する認証情報として機能します。ゲートウェイがバックエンドサービスにリクエストを送信する際、署名を計算してリクエストと共に渡します。バックエンドサービスは、対応する署名対象の文字列に対して対称計算を実行し、ゲートウェイのアイデンティティを検証できます。バックエンドサービスが VPC 内にあり、専用 VPC 環境の API などのように、プライベートネットワーク経由でゲートウェイに接続する場合、チャネルが安全であるためバックエンド署名は不要です。
従来の署名キー機能は、プラグインシステムに統合されました。既存のコンソールインターフェイスと API は引き続き利用できます。従来の署名キー機能とバックエンド署名プラグインは同じ種類のプラグインであり、同じアタッチ制限が適用されます。
従来の署名キー機能に対して API またはコンソールで行った変更は、プラグインシステムと同期されます。ただし、リモート同期はサポートされません。
2. プラグインのアタッチ
API にキーをアタッチすると、ゲートウェイはその API のバックエンドサービス宛てのすべてのリクエストに署名情報を含めます。バックエンドは、対称計算を実行して署名を検証し、ゲートウェイを認証する必要があります。
API のキーを置き換えるには、プラグイン内のキーとシークレットを直接変更できます。変更は、アタッチされているすべての API で直ちに有効になります。
3. プラグイン設定
プラグインは JSON または YAML 形式で設定できます。どちらの形式も同じスキーマを使用しており、YAML から JSON へのコンバーターを使用して相互に変換できます。次のコードブロックは、YAML 形式のテンプレートを示します。
---
type: APIGW_BACKEND
key: SampleKey
secret: SampleSecret
isGenerateContentSha256Header: false # (オプション) クライアントリクエストの "x-ca-signed-payload" を署名ヘッダーに追加するかどうかを指定します。デフォルト: false 4. API Gateway 署名の読み取り
ゲートウェイが計算した署名は、X-Ca-Proxy-Signature リクエストヘッダーに格納されます。
5. バックエンド署名ルール
署名計算の詳細な Java デモについては、https://github.com/aliyun/api-gateway-demo-sign-backend-java のサンプルコードをご参照ください。
署名計算の手順は次のとおりです。
API Gateway は、バックエンドに送信される HTTP リクエストから特定のデータを抽出し、それらを結合して署名対象の文字列を作成します。署名対象の文字列の形式は次のとおりです。
HTTPMethod Content-MD5 Headers PathAndParametersこれら 4 つのフィールドで署名対象の文字列を構成し、改行 (
\n) で区切ります。空のフィールドであっても、1 つの例外を除き改行を含める必要があります。Headersフィールドが空の場合は、その後に改行を追加しないでください。署名はケースセンシティブです。各フィールドの抽出ルールを次に示します。HTTPMethod:POSTなど、大文字の HTTP メソッド。Content-MD5: ゲートウェイは、クライアントリクエストのContent-MD5ヘッダーの値を読み取ります。クライアントがこのヘッダーを送信しない場合、署名対象の文字列内のContent-MD5値は空になります。クライアントは、リクエストにフォームエンコードされていないボディがある場合にのみ、Content-MD5ヘッダーを計算して送信する必要があります。次の Java コードは、Content-MD5値の計算方法を示します。String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getBytes("UTF-8")));Headers: このフィールドには、署名計算の対象となるすべてのヘッダーキーと値が含まれます。署名に含めるヘッダーのキーは、X-Ca-Proxy-Signature-Headersリクエストヘッダーから読み取られ、複数のキーはカンマで区切られます。この部分の文字列を構築するには、まず署名計算に含めるすべてのヘッダーキーをアルファベット順にソートします。次に、ヘッダーキーを小文字に変換し、次のようにキーと値を連結します。String headers = HeaderKey1.toLowerCase() + ":" + HeaderValue1 +"\n"+ HeaderKey2.toLowerCase() + ":" + HeaderValue2 +"\n"+ ... + HeaderKeyN.toLowerCase() + ":" + HeaderValueN + "\n"PathAndParametersこのフィールドには、パスと、クエリおよびフォームのすべてのパラメーターが含まれます。この文字列を構築するには、クエリまたはフォームパラメーターがある場合にパスの末尾に
?を追加します。次に、すべてのクエリおよびフォームパラメーターのキーをアルファベット順にソートし、次のように連結します。クエリまたはフォームパラメーターがない場合、PathAndParametersはパスのみです。String PathAndParameters = Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN説明クエリまたはフォームパラメーターは複数の値を持つ場合があります。パラメーターに複数の値がある場合、署名計算では最初の値のみが使用されます。パラメーターが存在する場合、値が空であっても、署名対象の文字列には等号 (
=) を含める必要があります。たとえば、クエリ文字列がpath?a=&bの場合、署名計算ではpath?a=&b=と記述する必要があります。
署名を計算します。
Mac hmacSha256 = Mac.getInstance("HmacSHA256"); byte[] keyBytes = secret.getBytes("UTF-8"); // secret は API にアタッチされた署名キーです hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256")); String sign = new String(Base64.encodeBase64(hmacSha256.doFinal(stringToSign.getBytes("UTF-8"))),"UTF-8");最終的な署名は、署名対象の文字列 (StringToSign) を UTF-8 でバイト配列にエンコードし、暗号化アルゴリズムでそのバイト配列を暗号化した後、暗号化結果を Base64 アルゴリズムでエンコードして生成されます。
6. デバッグモード
バックエンド署名の統合とテストを簡素化するために、API Gateway へのリクエストに X-Ca-Request-Mode: debug ヘッダーを追加してデバッグモードを有効にできます。
その後、バックエンドサービスは X-Ca-Proxy-Signature-String-To-Sign ヘッダーを読み取れます。このヘッダーでは、HTTP ヘッダーに改行を含めることができないため、改行文字が # に置き換えられます。
X-Ca-Proxy-Signature-String-To-Sign はバックエンド署名計算には含まれません。
7. タイムスタンプ検証
バックエンドでタイムスタンプ検証を実行する必要がある場合は、API 定義で CaRequestHandleTime システムパラメーターを選択できます。このパラメーターは、ゲートウェイがリクエストを受信した UTC 時刻を提供します。