プログラミング言語で利用できる SDK がない場合や、依存関係を直接管理する必要がある場合は、OpenAPI を使用してトークンを取得します。このトピックでは、リクエストパラメーター、署名メカニズム、レスポンス形式について説明し、Java と Python の例を示します。
認証情報の準備
この API には AccessKey ID と AccessKey Secret が必要です。ランタイム環境で ALIYUN_AK_ID と ALIYUN_AK_SECRET の環境変数を設定してください。以下の例では、これらの変数から認証情報を読み取ります。
AccessKey Secret とトークンは機密情報です。公開されるコードやログに含めないでください。以下の例では、トークンを含むレスポンスを出力します。このコードをアプリケーションに統合する際は、この情報を保護してください。
コード例
以下の例では、HTTPS GET リクエストを送信してトークンを取得します。レスポンス内の Token.Id はトークン値、Token.ExpireTime は秒単位の有効期限タイムスタンプです。
Java
JDK 8 以降を使用し、次の Maven 依存関係を追加してください。
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>3.9.1</version>
</dependency>
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Base64;
import java.util.Map;
import java.util.StringJoiner;
import java.util.TreeMap;
import java.util.UUID;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class CreateToken {
private static String encode(String value) throws Exception {
return URLEncoder.encode(value, "UTF-8")
.replace("+", "%20").replace("*", "%2A").replace("%7E", "~");
}
public static void main(String[] args) throws Exception {
String accessKeyId = System.getenv("ALIYUN_AK_ID");
String accessKeySecret = System.getenv("ALIYUN_AK_SECRET");
if (accessKeyId == null || accessKeyId.isEmpty()
|| accessKeySecret == null || accessKeySecret.isEmpty()) {
throw new IllegalArgumentException("Set ALIYUN_AK_ID and ALIYUN_AK_SECRET.");
}
String endpoint = "https://nlsmeta.ap-southeast-1.aliyuncs.com/";
Map<String, String> parameters = new TreeMap<>();
parameters.put("AccessKeyId", accessKeyId);
parameters.put("Action", "CreateToken");
parameters.put("Version", "2019-07-17");
parameters.put("RegionId", "ap-southeast-1");
parameters.put("Format", "JSON");
parameters.put("SignatureMethod", "HMAC-SHA1");
parameters.put("SignatureVersion", "1.0");
parameters.put("SignatureNonce", UUID.randomUUID().toString());
parameters.put("Timestamp", Instant.now().truncatedTo(ChronoUnit.SECONDS).toString());
StringJoiner query = new StringJoiner("&");
for (Map.Entry<String, String> entry : parameters.entrySet()) {
query.add(encode(entry.getKey()) + "=" + encode(entry.getValue()));
}
String canonicalQuery = query.toString();
String stringToSign = "GET&" + encode("/") + "&" + encode(canonicalQuery);
Mac mac = Mac.getInstance("HmacSHA1");
mac.init(new SecretKeySpec((accessKeySecret + "&").getBytes(StandardCharsets.UTF_8), "HmacSHA1"));
String signature = Base64.getEncoder().encodeToString(
mac.doFinal(stringToSign.getBytes(StandardCharsets.UTF_8)));
Request request = new Request.Builder()
.url(endpoint + "?" + canonicalQuery + "&Signature=" + encode(signature))
.get().build();
OkHttpClient client = new OkHttpClient();
try (Response response = client.newCall(request).execute()) {
String body = response.body() == null ? "" : response.body().string();
if (!response.isSuccessful()) {
throw new IllegalStateException("HTTP " + response.code() + ": " + body);
}
System.out.println(body);
}
}
}
Python
Python 3.4 以降を使用し、Requests をインストールしてください。
pip install requests
import base64
import hashlib
import hmac
import os
import uuid
from datetime import datetime, timezone
from urllib.parse import quote
import requests
def encode(value):
return quote(value, safe="-_.~")
def create_token():
access_key_id = os.environ["ALIYUN_AK_ID"]
access_key_secret = os.environ["ALIYUN_AK_SECRET"]
endpoint = "https://nlsmeta.ap-southeast-1.aliyuncs.com/"
parameters = {
"AccessKeyId": access_key_id,
"Action": "CreateToken",
"Version": "2019-07-17",
"RegionId": "ap-southeast-1",
"Format": "JSON",
"SignatureMethod": "HMAC-SHA1",
"SignatureVersion": "1.0",
"SignatureNonce": str(uuid.uuid4()),
"Timestamp": datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ"),
}
canonical_query = "&".join(
encode(key) + "=" + encode(value)
for key, value in sorted(parameters.items())
)
string_to_sign = "GET&" + encode("/") + "&" + encode(canonical_query)
signature = base64.b64encode(hmac.new(
(access_key_secret + "&").encode("utf-8"),
string_to_sign.encode("utf-8"), hashlib.sha1
).digest()).decode("ascii")
response = requests.get(
endpoint + "?" + canonical_query + "&Signature=" + encode(signature),
timeout=20,
)
if response.status_code != 200:
raise RuntimeError("HTTP {}: {}".format(response.status_code, response.text))
return response.text
if __name__ == "__main__":
print(create_token())
リクエストの詳細
この API は GET と POST をサポートし、Alibaba Cloud POP リクエスト署名を使用します。HTTP と HTTPS のリクエストは同じパラメーターを使用します。HTTPS の使用を推奨します。
エンドポイント
エンドポイント:https://nlsmeta.ap-southeast-1.aliyuncs.com/。リージョン ID:ap-southeast-1。API バージョン:2019-07-17。
リクエストパラメーター
|
名前 |
タイプ |
必須 |
説明 |
|
AccessKeyId |
String |
はい |
AccessKey ID です。 |
|
Action |
String |
はい |
操作名です。このパラメーターを |
|
Version |
String |
はい |
API バージョンです。このパラメーターを |
|
Format |
String |
いいえ |
レスポンス形式です。JSON 形式のレスポンスを取得するには、このパラメーターを |
|
RegionId |
String |
はい |
リージョン ID です。このパラメーターを |
|
Timestamp |
String |
はい |
UTC でのリクエストのタイムスタンプです。 |
|
SignatureMethod |
String |
はい |
署名アルゴリズムです。このパラメーターを |
|
SignatureVersion |
String |
はい |
署名アルゴリズムのバージョンです。このパラメーターを |
|
SignatureNonce |
String |
はい |
リプレイ攻撃を防ぐための一意のランダムな文字列です。リクエストごとに異なる値を使用してください。 |
|
Signature |
String |
はい |
|
ヘッダーとパラメーターの配置
GET の場合、パラメーターは URL のクエリ文字列に配置します。POST の場合、リクエストボディに配置します。
|
ヘッダー |
必須 |
説明 |
|
Host |
いいえ |
サービスのホスト名です。通常、HTTP クライアントがエンドポイントに基づいてこのヘッダーを設定します。 |
|
Accept |
いいえ |
クライアントが JSON を受け入れることを示すには、このヘッダーを |
|
Content-Type |
POST で必須 |
POST リクエストでは、このヘッダーを |
以下のテンプレートはリクエスト形式を示しています。<encoded-parameters> は、Signature を含む URL エンコードされたパラメーター文字列を表します。POST リクエストに署名する場合は、HTTP メソッドとして POST を使用してください。GET の署名は POST には再利用できません。
GET
GET /?<encoded-parameters> HTTP/1.1
Host: <endpoint-host>
Accept: application/json
POST
POST / HTTP/1.1
Host: <endpoint-host>
Accept: application/json
Content-Type: application/x-www-form-urlencoded
<encoded-parameters>
署名メカニズム
すべてのリクエストには署名を含める必要があります。クライアントは AccessKey Secret を使用して HMAC-SHA1 メッセージ認証コードを計算します。サーバーは AccessKey ID に基づいて対応するシークレットを取得し、署名を検証して呼び出し元を認証し、リクエストの完全性をチェックします。
正規化されたクエリ文字列の構築
Signatureパラメーターを除外し、残りのパラメーターを名前の辞書順 (大文字と小文字を区別) でソートしてください。各パラメーターの名前と値を UTF-8 を使用して URL エンコードしてください:
A-Z、a-z、0-9、-、_、.、~はエンコードしません。その他の文字は、UTF-8 の各バイトを
%XYとしてエンコードします。たとえば、二重引用符は%22としてエンコードします。スペースはプラス記号 (
+) ではなく%20としてエンコードしてください。
エンコードされた各名前と値を
=で連結し、その結果のペアを&で連結してください。最初のパラメーターの前に&は付けません。
percentEncode(name1)=percentEncode(value1)&percentEncode(name2)=percentEncode(value2)
Java の URLEncoder はフォームエンコーディングを使用します。その出力では、+ を %20 に、* を %2A に、%7E を ~ に置き換えてください。
署名対象の文字列の構築
大文字の HTTP メソッド、エンコードされたリクエストパス (/)、エンコードされた正規化されたクエリ文字列を & で連結してください。
StringToSign = HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)
署名の計算と追加
AccessKey Secret に
&を追加して、HMAC-SHA1 キーを形成してください。キーと署名対象の文字列を UTF-8 でエンコードし、HMAC-SHA1 値を計算し、その結果を Base64 エンコードしてください。
Base64 の結果を URL エンコードし、
Signature=<encoded-signature>としてリクエストパラメーターに追加してください。
Signature = Base64(HMAC-SHA1(AccessKeySecret + "&", StringToSign))
署名検証の例
以下の固定パラメーターを使用して、署名の実装をオフラインで確認できます。AccessKey ペアは架空のものであり、タイムスタンプは期限切れのため、これらの値を使用してトークンを取得することはできません。
AccessKeyId: my_access_key_id
AccessKeySecret: my_access_key_secret
Action: CreateToken
Format: JSON
SignatureMethod: HMAC-SHA1
SignatureVersion: 1.0
SignatureNonce: b924c8c3-6d03-4c5d-ad36-d984d3116788
Timestamp: 2019-04-18T08:32:31Z
HTTPMethod: GET
正規化されたクエリ文字列:
AccessKeyId=my_access_key_id&Action=CreateToken&Format=JSON&RegionId=ap-southeast-1&SignatureMethod=HMAC-SHA1&SignatureNonce=b924c8c3-6d03-4c5d-ad36-d984d3116788&SignatureVersion=1.0&Timestamp=2019-04-18T08%3A32%3A31Z&Version=2019-07-17
署名対象の文字列:
GET&%2F&AccessKeyId%3Dmy_access_key_id%26Action%3DCreateToken%26Format%3DJSON%26RegionId%3Dap-southeast-1%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3Db924c8c3-6d03-4c5d-ad36-d984d3116788%26SignatureVersion%3D1.0%26Timestamp%3D2019-04-18T08%253A32%253A31Z%26Version%3D2019-07-17
Base64 署名:
4TdrOuLHXJU+5C6s927Wkq2h+wc=
URL エンコードされた署名パラメーター:
Signature=4TdrOuLHXJU%2B5C6s927Wkq2h%2Bwc%3D
レスポンスの詳細
以下の説明は、Format=JSON の場合に適用されます。GET リクエストと POST リクエストは、同じレスポンス形式を使用します。
成功レスポンス
HTTP ステータスコードは 200 です。主なフィールドは次のとおりです。
|
フィールド |
タイプ |
説明 |
|
Token |
Object |
トークン値と有効期限が含まれます。 |
|
Token.Id |
String |
トークン値です。 |
|
Token.ExpireTime |
Long |
有効期限です。有効期間ではなく、秒単位の UNIX タイムスタンプです。たとえば、1553825814 は 2019-03-29 02:16:54 UTC に相当します。トークンはこの時刻より前まで有効です。 |
次の例は、レスポンス内の Token フィールドを示しています。
{
"Token": {
"Id": "<token>",
"ExpireTime": 1553825814
}
}
エラーレスポンス
HTTP ステータスコードが 200 以外の場合です。Code と Message に基づいてリクエストパラメーターを確認してください。
|
フィールド |
タイプ |
説明 |
|
RequestId |
String |
リクエスト ID です。トラブルシューティングに使用できます。 |
|
Code |
String |
エラーコードです。 |
|
Message |
String |
エラーメッセージです。 |
たとえば、AccessKey ID が存在しない場合、API は HTTP 404 とともに次のフィールドを返します。
{
"RequestId": "<request-id>",
"Code": "InvalidAccessKeyId.NotFound",
"Message": "Specified access key is not found."
}
関連トピック
一時的なデバッグには、コンソールでトークンを取得できます。
SDK を使用してリクエストの署名と送信を処理するには、「SDKを使用したトークンの取得」をご参照ください。