バックエンド署名 (以前は署名キーと呼ばれていました) は、作成してAPI Gatewayに発行するキーと秘密のペアです。 この鍵と秘密のペアは、アカウントとパスワードのペアと同様に機能します。 バックエンド署名プラグインがAPIにバインドされた後、API Gatewayはキーとシークレットペアを使用して、バックエンドサービスに指定されたリクエストに署名します。 バックエンドサービスは、受信したリクエストに対して対称暗号化も実行します。 API Gatewayの署名がバックエンドサービスの署名と一致している場合、API Gatewayは認証を渡します。
1. 概要
バックエンド署名 (以前は署名キーと呼ばれていました) は、作成してAPI Gatewayに発行するキーと秘密のペアです。 API Gatewayは、キーとシークレットペアを使用して、バックエンドサービスに指定されたリクエストに署名します。 バックエンドサービスは、受信したリクエストに対して対称暗号化も実行します。 API Gatewayの署名がバックエンドサービスの署名と一致している場合、API Gatewayは認証を渡します。 バックエンドサービスに仮想プライベートクラウド (VPC) 経由でアクセスする場合、送信チャネルが安全であるため、バックエンド署名を使用する必要はありません。
元の署名キー機能は、プラグインシステムに統合されています。 元の署名キーインターフェイスと対応するコンソールUIはまだ使用中です。 元の署名キー機能とバックエンド署名プラグインは同じプラグインタイプであり、そのタイプの拘束制限の対象となります。
元の署名キーインターフェイスまたはコンソールでキーを作成または変更すると、データの変更がプラグインシステムに同期されます。 ただし、プラグインシステムで行った変更は、元の署名キーインターフェイスまたはコンソールと同期できません。
2. プラグインバインディングPlug-in binding
キーとシークレットのペアをAPIにバインドすると、API Gatewayはバックエンドサービスに送信されるすべての対応するリクエストにペアを追加します。 バックエンドサービスは、対称計算を実行して署名情報を解析し、API Gatewayを認証します。
ペアを置き換える場合は、APIにバインドされているバックエンド署名プラグインのキーとシークレットを変更できます。 変更内容はすぐに有効になります。
3. プラグインの設定
JSONまたはYAML形式でプラグインを設定できます。 2つの形式は同じスキーマを持ちます。 変換ツールを使用して、構成形式を変換できます。 次のコードは、YAMLの構成テンプレートです。
---
type: APIGW_BACKEND
key: SampleKey
secret: SampleSecret
4. 署名の読み取り
署名は、リクエストの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で区切られています。 Headersフィールドが空の場合、\nは必要ありません。 その他のフィールドが空の場合は、\nを保持する必要があります。 署名は大文字と小文字を区別します。 各フィールドのデータ抽出は、次のルールに従います。
HTTPMethod: POSTなどのリクエストの送信に使用されるHTTPメソッド。 このフィールドの値は大文字です。
Content-MD5: クライアントから送信されたリクエストの対応するヘッダーから取得されるContent-MD5値。 クライアントがContent-MD5ヘッダーを渡さない場合、署名文字列のContent-MD5値は空のままになります。 クライアントは、リクエストにボディがあり、ボディがフォームでない場合にのみ、Content-MD5ヘッダーを計算して送信します。 次のコードは、JAVAでのContent-MD5値の計算方法を示しています。
String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
ヘッダー: 署名計算に含まれるすべてのヘッダーのキーと値。 キーは、リクエストヘッダーからX-Ca-Proxy-Signature-headers形式で読み取られます。 複数のキーはコンマ (,) で区切ります。 署名計算に関与するキーは、アルファベット順にソートされ、小文字に変換され、次の規則に基づいて連結されます。
String headers = HeaderKey1.toLowerCase() + ":" + HeaderValue1 +"\n"+ HeaderKey2.toLowerCase() + ":" + HeaderValue2 +"\n"+ ... + HeaderKeyN.toLowerCase() + ":" + HeaderValueN + "\n"
PathAndParameters
このフィールドには、[パス] 、[クエリ] 、および [フォーム] セクションのすべてのパラメーターが含まれます。 QueryまたはFormパラメーターが存在する場合、疑問符 (?) が追加されます。 次に、クエリおよびフォームパラメータのキーがアルファベット順にソートされ、次のルールに基づいて連結されます。 QueryまたはFormパラメーターが存在しない場合、PathAndParametersはPathに設定されます。
String PathAndParameters = Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN
注: QueryまたはFormパラメーターには複数の値があります。 もしそうであれば、最初の値のみが署名計算に使用される。 パラメーターが渡されている限り、計算中は状況に関係なく等号 (=) を保持する必要があります。 たとえば、2つのクエリパラメーターの形式が "path?a=&b" の場合、署名に "path?a=&b=" と記述する必要があります。
次いで、署名が計算される。 次のコードスニペットは例を示します。
Mac hmacSha256 = Mac.getInstance("HmacSHA256");
byte[] keyBytes = secret.getBytes("UTF-8"); //The secret value is the secret in the signature key bound to the API.
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
String sign = new String(Base64.encodeBase64(Sha256.doFinal(stringToSign.getBytes("UTF-8")),"UTF-8"));
まず、StringToSignをUTF-8-decodedした後にByte配列を取得します。 次いで、バイト配列を暗号化し、Base64-encodedして最終署名を生成する。
6. デバッグモード
バックエンド署名に効率的にアクセスしてデバッグするには、[デバッグ] モードを有効にします。 デバッグ手順では、API Gatewayに送信されるリクエストのヘッダーとしてX-Ca-Request-Mode = debugを追加します。
バックエンドサービスは、HTTPヘッダー内のX-Ca-Proxy-Signature-String-To-Signヘッダーを読み取ることができます。 HTTPヘッダーでは改行を許可しないため、改行はHTTPヘッダーの番号記号 (#) に置き換えられます。
注: X-Ca-Proxy-Signature-String-To-Signは、バックエンド署名の計算には関与しません。
7. タイムスタンプ検証
バックエンドサービスがリクエストのタイムスタンプを確認する必要がある場合は、API GatewayがAPI定義でリクエストを受信したときに、CaRequestHandleTimeをグリニッジ標準時 (GMT) に設定できます。