阿里云API网关签名算法:使用摘要签名认证方式调用API

先看一下请求参数:

HTTPMethod
Accept
Content-MD5
Content-Type
Date
Headers
PathAndParameters

生成签名字串时,顺序必须按照以上排列,参数是通过Header头发送的,下面对每个参数进行说明。

HTTPMethod: HTTP请求方法,必须大写,例如:GET、POST

Accept: 请求中的Accept头,建议明确指定,否则有些浏览器会自动添加/而导致签名失败。

Content-MD5: 请求中的Content-MD5头,当请求存在Body且Body并非Form形式时,需要计算Content-MD5的值,当Content-MD5的值为空时,需要添加换行符\n。Content-MD5的计算示例如下:

$bytes = 'Stream的内容';
$content = '';
foreach($bytes as $byte) { 
    $content .= chr($byte); 
}
$content_md5 = base64_encode(md5($content, true);

Content-Type: 请求中的Content-Type头的值。

Date: 请求中的Date头,北京时间,RFC 2822 格式的日期。

Headers: 可以指定额外的Header头用于签名,从而增加安全性。参与签名计算的Headers需要按Key字典排序,拼接方式如下:

Key:Value\n

如果某个Key的值为空,也需要保留Key和冒号。

PathAndParameters: 包含Path和请求参数,拼接方式如下:

Path?Key1=Value1&Key2=Value2&Key3=Value3

Path是指API请求地址中的目录部分。

以上为签名需要的所有参数,加密方法可以为(默认HmacSHA256):

  • HmacSHA256
  • HmacSHA1

使用APP Secret加密后再进行base64_encode编码就得到了签名字串:

$sign = base64_encode(hash_hmac('sha256', $sign_str, $app_secret, true));

签名字串包含在Header头中:

X-Ca-Signature:签名字串

还需要发送的Header头:

X-Ca-Signature-Headers:值为Headers(以上Headers参数)的Key

签名字串示例:

GET
application/json; charset=utf-8

application/x-www-form-urlencoded; charset=UTF-8
Sun, 18 Apr 2021 16:47:16 +0800
X-Ca-Key:APP Key
X-Ca-Nonce:d9fa0c5d-124a-166d-5298-31adf901e202
X-Ca-Signature-Method:HmacSHA256
X-Ca-Timestamp:1618735870000
Path?Key1=Value1&Key2=Value2&Key3=Value3

以上字串是为了直观,将\n显示为换行了。注意以上字串,Headers参数包含了四个:

  • X-Ca-Key:在阿里云市场购买API接口后就可以获得APP Key;
  • X-Ca-Nonce:可以自行生成UUID;
  • X-Ca-Signature-Method:加密方法(HmacSHA256);
  • X-Ca-Timestamp:时间戳,北京时间,需要为毫秒,即time()*1000。

发送的Header头如下:

$headers = array(
    'Accept' => 'application/json; charset=utf-8',
    'Content-MD5' => '',
    'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8',
    'Date' => date('r'),
    'X-Ca-Key' => $app_key,
    'X-Ca-Nonce' => d9fa0c5d-124a-166d-5298-31adf901e202,
    'X-Ca-Signature-Method' => 'HmacSHA256',
    'X-Ca-Timestamp' => strval(time()*1000),
    'X-Ca-Signature-Headers' => 'X-Ca-Key,X-Ca-Nonce,X-Ca-Signature-Method,X-Ca-Timestamp',
    'X-Ca-Signature' => $sign,
);

UUID生成函数参考:

function bzg_get_uuid() {
	$str = md5(uniqid(mt_rand(), true));
	return substr($str, 0, 8) . '-' 
		. substr($str, 8, 4) . '-' 
		. substr($str, 12, 4) . '-' 
		. substr($str, 16, 4) . '-' 
		. substr($str, 20, 12);
}
阿里云