阿里云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头用于签名,从而增加安全性。可以不带任何参数先向API接口发起一次请求,获得返回的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,
);

以上示例为了简洁,没有进行原始HTTP请求,当然这样请求也会成功。如果希望更安全一些,则可以先不带参数请求一次,将返回的Headers加入签名计算中。

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);
}
个赞
扫码关注背字根

一个热爱Web开发的大男孩