Catatan:
Jika Anda menggunakan SDK yang disediakan oleh Alibaba Cloud, Anda tidak perlu mengikuti mekanisme tanda tangan ini. SDK tersedia untuk Java, PHP, dan C#.
API mendukung permintaan yang dikirimkan menggunakan metode GET dan POST. Namun, StringToSign berbeda untuk permintaan GET dan POST.
Direct Mail mengautentikasi setiap permintaan akses. Oleh karena itu, Anda harus menyertakan informasi tanda tangan dalam setiap permintaan, baik menggunakan protokol HTTP maupun HTTPS. Direct Mail menggunakan enkripsi simetris dengan ID AccessKey dan Rahasia AccessKey untuk memverifikasi identitas pengirim permintaan. ID AccessKey dan Rahasia AccessKey merupakan bagian dari Informasi AccessKey yang diterbitkan oleh Alibaba Cloud. Anda dapat melihat dan mengelola Informasi AccessKey Anda di bagian User Information Management pada Konsol Manajemen Alibaba Cloud. ID AccessKey mengidentifikasi pemohon, sedangkan Rahasia AccessKey adalah kunci yang digunakan untuk mengenkripsi string tanda tangan dan memverifikasi tanda tangan di server. Anda harus menjaga kerahasiaan Informasi AccessKey Anda.
Langkah-langkah penandatanganan
Untuk menandatangani permintaan, lakukan langkah-langkah berikut:
Buat string kueri kanonis dari parameter permintaan.
a. Urutkan parameter.
Urutkan semua parameter permintaan—termasuk parameter umum dan parameter khusus API—secara alfabetis berdasarkan nama. Parameter Signature tidak disertakan dalam proses penandatanganan.
Catatan: Untuk permintaan GET, parameter tersebut merupakan bagian dari URL permintaan yang mengikuti
?dan dipisahkan oleh&.b. Enkode nama dan nilai setiap parameter permintaan.
Lakukan URL-encode terhadap nama dan nilai parameter menggunakan set karakter UTF-8. Aturan URL encoding adalah sebagai berikut:
Jangan enkode karakter A–Z, a–z, 0–9, atau karakter khusus
-,_,., dan~.Enkode karakter lain ke dalam format
%XY.XYmerepresentasikan nilai heksadesimal dari kode ASCII karakter tersebut. Sebagai contoh, tanda kutip ganda (") dienkode menjadi%22.Enkode karakter UTF-8 yang diperluas ke dalam format
%XY%ZA….Spasi harus dienkode sebagai
%20, bukan tanda plus (+).
Penting: Pustaka yang mendukung URL encoding, seperti
java.net.URLEncoderdalam Java, biasanya melakukan enkode berdasarkan aturan untuk tipe MIME (Multipurpose Internet Mail Extensions)application/x-www-form-urlencoded. Jika Anda menggunakan pustaka ini untuk enkode, Anda harus mengganti+dengan%20,*dengan%2A, dan%7Edengan~setelah enkode agar sesuai dengan aturan di atas.c. Gunakan tanda sama dengan (
=) untuk menghubungkan nama parameter yang telah dienkode dan nilainya.d. Gunakan tanda ampersand (
&) untuk menghubungkan parameter permintaan yang telah dienkode sesuai urutan dari langkah a. Hasilnya adalah string kueri kanonis.Gunakan string kueri kanonis dari langkah sebelumnya untuk membuat string yang akan ditandatangani (StringToSign) dalam format berikut:
StringToSign= HTTPMethod + "&" + percentEncode("/") + "&" + percentEncode(CanonicalizedQueryString)HTTPMethod adalah metode HTTP yang digunakan untuk mengirimkan permintaan, seperti GET atau POST.
percentEncode("/") adalah nilai yang diperoleh dengan mengenkode karakter
/berdasarkan aturan URL encoding yang dijelaskan pada langkah 1.b. Nilainya adalah%2F.percentEncode(CanonicalizedQueryString) adalah string yang diperoleh dengan mengenkode string kueri kanonis dari langkah 1 berdasarkan aturan URL encoding pada langkah 1.b. Catatan: Hasil dari percentEncode(CanonicalizedQueryString) dienkode dua kali (double-encoded).
Hitung nilai Hash-based Message Authentication Code (HMAC).
Hitung nilai HMAC untuk StringToSign dari langkah 2 sebagaimana didefinisikan dalam RFC2104.
Catatan: Saat menghitung tanda tangan, kuncinya adalah Rahasia AccessKey Anda diikuti oleh karakter ampersand (
&) (kode ASCII 38). Algoritma hash yang digunakan adalah SHA1.Hitung nilai tanda tangan.
Enkode nilai HMAC dari langkah 3 menjadi string menggunakan enkode Base64. Hasilnya adalah nilai tanda tangan (Signature).
Tambahkan nilai tanda tangan yang dihasilkan ke parameter permintaan sebagai parameter Signature. Proses penandatanganan permintaan selesai.
Catatan: Saat Anda mengirimkan nilai tanda tangan ke server Direct Mail sebagai parameter permintaan, nilai tersebut harus dienkode URL dengan cara yang sama seperti parameter lainnya, sesuai aturan dalam RFC3986.
Contoh tanda tangan
Contoh ini menunjukkan cara memanggil API SingleSendMail dengan mengirimkan permintaan POST melalui HTTPS.
URL permintaan adalah http://dm.aliyuncs.com/.
Parameter permintaan adalah sebagai berikut:
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 adalah sebagai berikut:
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-23Jika ID AccessKey adalah testid dan Rahasia AccessKey adalah testsecret, kunci untuk menghitung HMAC adalah testsecret&. Nilai tanda tangan yang dihitung adalah sebagai berikut:
llJfXJjBW3OacrVgxxsITgYaYm0=Setelah ditandatangani, parameter dalam badan permintaan POST ke http://dm.aliyuncs.com/ adalah sebagai berikut. Parameter Signature ditambahkan, dan header permintaan Content-Type diubah menjadi 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-23Kode di atas menunjukkan parameter yang diperlukan untuk badan permintaan sebelum enkode. Parameter-parameter ini harus dienkode sebelum Anda mengirimkan permintaan aktual..
Contoh kode
Java
private static final String MAC_NAME ="HmacSHA1";
private static final String ENCODING ="UTF-8";
/**
* Menandatangani encryptText menggunakan metode HMAC-SHA1.
*
*@param encryptText String yang akan ditandatangani.
*@param encryptKey Kunci.
*@return
*@throws Exception
*/
public static byte[] HmacSHA1Encrypt(StringencryptText, String encryptKey) throwsException {
byte[] data = encryptKey.getBytes(ENCODING);
// Membuat kunci dari array byte yang diberikan. Parameter kedua menentukan nama algoritma kunci.
SecretKey secretKey = new SecretKeySpec(data,MAC_NAME);
// Menghasilkan objek Mac untuk algoritma Mac yang ditentukan.
Mac mac = Mac.getInstance(MAC_NAME);
// Menginisialisasi objek Mac dengan kunci yang diberikan.
mac.init(secretKey);
byte[] text = encryptText.getBytes(ENCODING);
// Menyelesaikan operasi 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
# Ganti StringToSign dengan konten sebenarnya.
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;
}
// Ganti StringToSign dengan konten sebenarnya.
echo encryptTokey(StringToSign);
?>FAQ
Jika Anda kadang-kadang menerima kesalahan SignatureDoesNotMatch saat menggunakan API, hal ini terjadi karena karakter khusus dalam string yang dienkode tidak diganti. Untuk informasi selengkapnya, lihat bagian Penting di atas.
Jika Anda tidak dapat menyelesaikan masalah ketidakcocokan tanda tangan atau tidak yakin cara menggunakan mekanisme tanda tangan, lihat Contoh permintaan. Anda dapat mengganti parameter dalam contoh tersebut dengan milik Anda sendiri.