注:
Alibaba Cloud が提供する SDK を使用する場合、この署名メカニズムに従う必要はありません。SDK は Java、PHP、C# で利用できます。
API は GET および POST メソッドを使用して送信されるリクエストをサポートします。ただし、StringToSign は GET リクエストと POST リクエストで異なります。
Direct Mail はすべてのアクセスリクエストを認証します。したがって、HTTP または HTTPS プロトコルを使用するかどうかに関係なく、すべてのリクエストに署名情報を含める必要があります。Direct Mail は、AccessKey ID と AccessKey Secret を使用した対称暗号化を使用して、リクエスト送信者の ID を検証します。AccessKey ID と AccessKey Secret は、Alibaba Cloud によって発行された AccessKey 情報の一部です。Alibaba Cloud 管理コンソールの [ユーザー情報管理] セクションで AccessKey 情報を表示および管理できます。AccessKey ID はリクエスターを識別します。AccessKey Secret は、署名文字列を暗号化し、サーバーで署名を検証するために使用されるキーです。AccessKey 情報は厳重に機密扱いにする必要があります。
署名ステップ
リクエストに署名するには、次のステップを実行します。
リクエストパラメーターから正規化されたクエリ文字列を作成します。
a. パラメーターをソートします。
共通パラメーターと API 固有のパラメーターを含むすべてのリクエストパラメーターを、名前のアルファベット順にソートします。Signature パラメーターは署名プロセスには含まれません。
注: GET リクエストの場合、これらのパラメーターはリクエスト URL の
?の後の部分であり、&で区切られます。b. 各リクエストパラメーターの名前と値をエンコードします。
UTF-8 文字セットを使用して、パラメーター名と値を URL エンコードします。URL エンコーディングのルールは次のとおりです。
文字 A-Z、a-z、0-9、または特殊文字
-、_、.、~はエンコードしません。他の文字は
%XYフォーマットにエンコードします。XYは、文字の ASCII コードの 16 進数値を表します。たとえば、二重引用符 (") は%22としてエンコードされます。拡張 UTF-8 文字は
%XY%ZA…フォーマットにエンコードします。スペースは、プラス記号 (
+) ではなく、%20としてエンコードする必要があります。
重要: Java の
java.net.URLEncoderなど、URL エンコーディングをサポートするライブラリは、通常、application/x-www-form-urlencodedMultipurpose Internet Mail Extensions (MIME) タイプのルールに基づいてエンコードします。これらのライブラリを使用してエンコーディングを行う場合、エンコーディング後に+を%20に、*を%2Aに、%7Eを~に置き換えて、前述のルールに準拠した文字列を作成する必要があります。c. 等号 (
=) を使用して、エンコードされたパラメーター名とその値を連結します。d. アンパサンド (
&) を使用して、ステップ a の順序でエンコードされたリクエストパラメーターを連結します。その結果が正規化されたクエリ文字列です。前のステップで作成した正規化されたクエリ文字列を使用して、次のフォーマットで署名する文字列を作成します。
StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)HTTPMethod は、GET や POST など、リクエストの送信に使用される HTTP メソッドです。
percentEncode("/") は、ステップ 1.b で説明した URL エンコーディングルールに基づいて
/文字をエンコードして得られる値です。値は%2Fです。percentEncode(CanonicalizedQueryString) は、ステップ 1 の正規化されたクエリ文字列をステップ 1.b の URL エンコーディングルールに基づいてエンコードして得られる文字列です。注:percentEncode(CanonicalizedQueryString) の結果は二重にエンコードされます。
ハッシュベースのメッセージ認証コード (HMAC) 値を計算します。
RFC2104 で定義されているように、ステップ 2 の StringToSign の HMAC 値を計算します。
注:署名を計算する際、キーは AccessKeySecret の後にアンパサンド (
&) 文字 (ASCII コード 38) を付けたものです。ハッシュアルゴリズムは SHA1 です。署名値を計算します。
ステップ 3 の HMAC 値を Base64 エンコーディングを使用して文字列にエンコードします。その結果が署名値 (Signature) です。
結果の署名値を Signature パラメーターとしてリクエストパラメーターに追加します。これでリクエストの署名プロセスは完了です。
注:署名値をリクエストパラメーターとして Direct Mail サーバーに送信する場合、RFC3986 のルールに基づいて、他のパラメーターと同様に URL エンコードする必要があります。
署名の例
この例では、HTTPS 経由で POST リクエストを送信して SingleSendMail API を呼び出す方法を示します。
リクエスト URL は http://dm.aliyuncs.com/ です。
リクエストパラメーターは次のとおりです。
AccessKeyId=testid&AccountName=<a%b'>&Action=SingleSendMail&AddressType=1&Format=XML&HtmlBody=4&RegionId=cn-hangzhou&ReplyToAddress=true&SignatureMethod=HMAC-SHA1&SignatureNonce=c1b2c332-4cfb-4a0f-b8cc-ebe622aa0a5c&SignatureVersion=1.0&Subject=3&TagName=2&Timestamp=2016-10-20T06:27:56Z&ToAddress=1@test.com&Version=2015-11-23StringToSign は次のとおりです。
POST&%2F&AccessKeyId%3Dtestid%26AccountName%3D%253Ca%2525b%2527%253E%26Action%3DSingleSendMail%26AddressType%3D1%26Format%3DXML%26HtmlBody%3D4%26RegionId%3Dcn-hangzhou%26ReplyToAddress%3Dtrue%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3Dc1b2c332-4cfb-4a0f-b8cc-ebe622aa0a5c%26SignatureVersion%3D1.0%26Subject%3D3%26TagName%3D2%26Timestamp%3D2016-10-20T06%253A27%253A56Z%26ToAddress%3D1%2540test.com%26Version%3D2015-11-23AccessKeyId が testid で、AccessKeySecret が testsecret の場合、HMAC を計算するためのキーは testsecret& です。計算された署名値は次のとおりです。
llJfXJjBW3OacrVgxxsITgYaYm0=署名後、http://dm.aliyuncs.com/ への POST リクエストの本文のパラメーターは次のようになります。Signature パラメーターが追加され、Content-Type リクエストヘッダーが `application/x-www-form-urlencoded` に変更されます。
Signature=llJfXJjBW3OacrVgxxsITgYaYm0=&AccessKeyId=testid&AccountName=<a%b'>&Action=SingleSendMail&AddressType=1&Format=XML&HtmlBody=4&RegionId=cn-hangzhou&ReplyToAddress=true&SignatureMethod=HMAC-SHA1&SignatureNonce=c1b2c332-4cfb-4a0f-b8cc-ebe622aa0a5c&SignatureVersion=1.0&Subject=3&TagName=2&Timestamp=2016-10-20T06:27:56Z&ToAddress=1@test.com&Version=2015-11-23前述のコードは、エンコーディング前のリクエストボディの必須パラメーターを示しています。これらのパラメーターは、実際のリクエストを送信する前にエンコーディングする必要があります。「」をご参照ください。
コード例
Java
private static final String MAC_NAME ="HmacSHA1";
private static final String ENCODING ="UTF-8";
/**
* HMAC-SHA1 メソッドを使用して encryptText を署名します。
*
*@param encryptText 署名される文字列。
*@param encryptKey キー。
*@return
*@throws Exception
*/
public static byte[] HmacSHA1Encrypt(StringencryptText, String encryptKey) throwsException {
byte[] data = encryptKey.getBytes(ENCODING);
// 指定されたバイト配列からキーを作成します。2 番目のパラメーターはキーアルゴリズムの名前を指定します。
SecretKey secretKey = new SecretKeySpec(data,MAC_NAME);
// 指定された Mac アルゴリズムの Mac オブジェクトを生成します。
Mac mac = Mac.getInstance(MAC_NAME);
// 指定されたキーで Mac オブジェクトを初期化します。
mac.init(secretKey);
byte[] text = encryptText.getBytes(ENCODING);
// Mac 操作を完了します。
return mac.doFinal(text);
}
@Test
public void test() throws Exception {
/*StringToSign=
HTTPMethod + “&” +
percentEncode(“/”) + ”&” +
percentEncode(CanonicalizedQueryString)*/
String str ="AccessKeyId=testid&AccountName=<a%b'>&Action=SingleSendMail&AddressType=1&Format=XML&HtmlBody=4&RegionId=cn-hangzhou&ReplyToAddress=true&SignatureMethod=HMAC"+
"-SHA1&SignatureNonce=c1b2c332-4cfb-4a0f-b8cc-ebe622aa0a5c&SignatureVersion=1.0&Subject=3&TagName=2&Timestamp=2016-10-20T06:27:56Z&ToAddress=1@test.com&Version=2015-11-23";
String percentStr = "";
String[] strs = str.split("&");
for (int i = 0; i < strs.length;i++) {
String[] str1 =strs[i].split("=");
if (str1.length == 1){
percentStr = percentStr + getUtf8Encoder(str1[0])+ "=" + getUtf8Encoder("")+ "&";
}else {
percentStr = percentStr + getUtf8Encoder(str1[0])+ "=" + getUtf8Encoder(str1[1]) + "&";
}
}
percentStr =percentStr.substring(0,percentStr.lastIndexOf("&"));
String percent = URLEncoder.encode("/","UTF-8");
percentStr = getUtf8Encoder(percentStr);
String toSign = HttpMethod.POST + "&"+ percent +"&" + percentStr;
System.out.println("--------------"+ toSign);
/*POST&%2F&AccessKeyId%3Dtestid%26AccountName%3D%253Ca%2525b%2527%253E%26Action%3DSingleSendMail%26AddressType%3D1%26Format%3DXML%26HtmlBody%3D4%26RegionId%3Dcn-hangzhou%26ReplyToAddress%3Dtrue%26SignatureMethod%3DHMAC-SHA1%26SignatureNonce%3Dc1b2c332-4cfb-4a0f-b8cc-ebe622aa0a5c%26SignatureVersion%3D1.0%26Subject%3D3%26TagName%3D2%26Timestamp%3D2016-10-20T06%253A27%253A56Z%26ToAddress%3D1%2540test.com%26Version%3D2015-11-23*/
byte[] bytes = HmacSHA1Encrypt(toSign,"testsecret&");
String base64Str = Base64.encode(bytes);
System.out.println(base64Str);//llJfXJjBW3OacrVgxxsITgYaYm0=
}
private String getUtf8Encoder(String param) throwsUnsupportedEncodingException {
return URLEncoder.encode(param, "UTF-8")
.replaceAll("\\+","%20")
.replaceAll("\\*","%2A")
.replaceAll("%7E","~");
};Python
import hmac
import base64
# StringToSign を実際のコンテンツに置き換えます。
message = b'StringToSign'
key = b'testsecret&'
h = hmac.new(key, message, digestmod='sha1')
# print(h.digest())
print(base64.b64encode(h.digest()))PHP
<?php
function encryptTokey($data){
$apikey = 'testsecret&';
$sign = base64_encode(hash_hmac("sha1", $data, $apikey, true));
//printf($sign);
return $sign;
}
// StringToSign を実際のコンテンツに置き換えます。
echo encryptTokey(StringToSign);
?>よくある質問
API の使用中に SignatureDoesNotMatch エラーが断続的に発生する場合、このエラーは、エンコードされた文字列内の特殊文字が置き換えられていないために発生します。詳細については、上記の「重要」セクションをご参照ください。
署名の不一致の問題を解決できない場合、または署名メカニズムの使用方法がわからない場合は、「リクエストの例」をご参照ください。例のパラメーターを独自のパラメーターに置き換えることができます。