签名机制

ROA 风格 API 签名包含两部分:公共请求头(HTTP 协议 Header 参数和阿里云协议 Header 参数)和 CanonicalizedResource(规范资源),Body 不直接计入签名。

公共请求头

名称

描述

Authorization

用于验证请求合法性的认证信息,采用 acs AccessKeyId:signature 格式。

Content-Length

RFC 2616 中定义的 HTTP 请求内容长度。

Content-Type

RFC 2616 中定义的 HTTP 请求内容类型。

Content-MD5

HTTP 协议消息体的 128-bit MD5 散列值转换成 BASE64 编码的结果。为了防止所有请求被篡改,建议所有请求都附加该信息。

Date

描述请求时间。GMT 格式,例如:Wed, 26 Aug. 2015 17:01:00 GMT。

Accept

客户端需要的返回值类型,支持 application/json 和 application/xml。

Host

访问 Host 值,例如:ros.aliyuncs.com。

x-acs-signature-nonce

唯一随机数,用于防止网络重放攻击。用户在不同请求中要使用不同的随机数值。

x-acs-signature-method

签名方法,目前只支持 HMAC-SHA1。

x-acs-signature-version

签名版本,目前是 1.0。

签名计算方法

ROA 风格的 API 请求使用标准的 Authorization 头来签名自己的请求,请求格式如下:

Authorization: acs AccessKeyId:Signature

HTTP 协议 Header

计算签名必须包含参数,Accept、Content-MD5、Content-Type、Date 的值(没有 key)(Content-Length 不计入签名),并按顺序排列;若值不存在则以 “\n” 补齐。

阿里云协议 Header (CanonicalizedHeaders)

CanonicalizedHeaders(阿里云规范头)是非标准 HTTP 头部信息。是指请求中出现的以 "x-acs-" 为前缀的参数信息。

构成阿里云规范头的方法如下:

  1. 将所有以 “x-acs-” 为前缀的 HTTP 请求头的名称转换成小写字母。如 “X-acs-OSS-Meta-Name: TaoBao” 转换成 “x-acs-oss-meta-name: TaoBao”。阿里云规范请求头的名称大小写不敏感,建议全小写。

  2. 如果一个公共请求头的值过长,则需要处理其中的 “\t”、“\n”、“\r”、“\f” 分隔符,将其替换成英文半角的空格。

  3. 将上一步得到的所有 HTTP 阿里云规范头按照字典顺序进行升序排列。

  4. 删除请求头和内容之间分隔符两端出现的任何空格。如 “x-acs-oss-meta-name: TaoBao,Alipay” 转换成 “x-acs-oss-meta-name:TaoBao,Alipay” 。

  5. 将所有的头和内容用 “\n” 分隔符分隔,拼成最后的 CanonicalizedHeaders。

CanonicalizedResource 和 qureyString

CanonicalizedResource 表示用户想要访问资源的规范描述,需要将子资源和 qurey 一同按照字典序,从小到大排列并以&为分隔符生成子资源字符串(问号?后的所有参数)。

例如:

https://codeup.cn-hangzhou.aliyuncs.com/api/v3/projects
?Sync=true&OrganizationId=5ef0767baf80fad018f11bfa&AccessToken=xxxxxx

排序后

/api/v3/projects?AccessToken=xxxxx&OrganizationId=5ef0767baf80fad018f11bfa&Sync=true

封装签名

  1. 计算StringToSign

    StringToSign =
     <HTTP-Verb> + "\n" +
         <Accept> + "\n" +
         <Content-MD5> + "\n" +
         <Content-Type> + "\n" +
         <Date> + "\n" + 
     <CanonicalizedHeaders> + 
     <CanonicalizedResource>

  2. 计算签名

    Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )
  3. 在请求 Header 中使用签名

    Authorization = acs AccessKeyId + ":" + Signature

示例

以创建代码库CreateRepository为例,下文介绍如何使用 HTTP 方式调用 Codeup API。

请求基本信息

curl -X POST 
-H "Accept: application/json"
-H "Content-MD5: Gmc1WBzxt5rYUOANwp732Q=="
-H "Content-Type: application/json"
-H "Date: Wed, 12 Aug 2020 09:23:49 GMT"
-H "x-acs-signature-method: HMAC-SHA1" 
-H "x-acs-signature-version: 1.0" 
-H "x-acs-version:2020-04-14"
-d "{\"name\":\"repo_name\",\"path\":\"repo_path\",\"visibility_level\":10}"
https://codeup.cn-hangzhou.aliyuncs.com/api/v3/projects
?OrganizationId=5ef0767baf80fad018f11bfa
&Sync=true
&AccessToken=xxxxx

计算StringToSign

  • 通用请求头

    stringToSign =
     <HTTP-Verb> + "\n" +
         <Accept> + "\n" +
         <Content-MD5> + "\n" +
         <Content-Type> + "\n" +
         <Date> + "\n"

    即:

    stringToSign =
     "POST\napplication/json\nGmc1WBzxt5rYUOANwp732Q==\napplication/json\nWed, 12 Aug 2020 09:23:49 GMT\n"

    其中,Content-MD5 为 body 参数 MD5 散列值转换成 BASE64 编码的结果。

  • 阿里云请求头

    stringToSign +=
     "x-acs-signature-method:HMAC-SHA1\nx-acs-signature-version:1.0\nx-acs-version:2020-04-14\n"
  • CanonicalizedResource 和 qureyString

    stringToSign +=
     "/api/v3/projects?AccessToken=xxxxx&OrganizationId=5ee760aa892c58bb7c3947c8&Sync=true"

计算签名

stringToSign = "POST\napplication/json\nGmc1WBzxt5rYUOANwp732Q==\napplication/json\nWed, 12 Aug 2020 09:23:49 GMT\nx-acs-signature-method:HMAC-SHA1\nx-acs-signature-version:1.0\nx-acs-version:2020-04-14\n/api/v3/projects?AccessToken=xxxxx&OrganizationId=5ee760aa892c58bb7c3947c8&Sync=true"

Signature算法(使用AccessKeySecret作为HMAC-SHA1的key签名):

Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )

Signature计算结果:

Signature = Jo3hw5KIa9iM6pPhU7xxxxxxxxx=

调用API

curl -X POST 
-H "Authorization: acs LTAI4GFXk3XrgCD5xxxxxxxx:Jo3hw5KIa9iM6pPhU7xxxxxxxxx="
-H "Accept: application/json"
-H "Content-MD5: Gmc1WBzxt5rYUOANwp732Q=="
-H "Content-Type: application/json"
-H "Date: Wed, 12 Aug 2020 09:23:49 GMT"
-H "x-acs-signature-method: HMAC-SHA1" 
-H "x-acs-signature-version: 1.0" 
-H "x-acs-version:2020-04-14"
-d "{\"name\":\"repo_name\",\"path\":\"repo_path\",\"visibility_level\":10}"
https://codeup.cn-hangzhou.aliyuncs.com/api/v3/projects
?OrganizationId=5ef0767baf80fad018f11bfa
&Sync=true
&AccessToken=xxxxx

如果签名校验不一致错误,会返回如下错误:

{
    "RequestId":"FD47108F-17A8-41BE-8878-AAD883C20B3D",
    "Message":"Specified signature is not matched with our calculation. server string to sign is:POST
application/json
Gmc1WBzxt5rYUOANwp732Q==
application/json
Wed, 12 Aug 2020 11:58:59 GMT
x-acs-signature-method:HMAC-SHA1
x-acs-signature-version:1.0
x-acs-version:2020-04-14
/api/v3/projects?OrganizationId=5ef0767baf80fad018f11bfa&Sync=true",
    "Recommend":"https://error-center.aliyun.com/status/search?Keyword=SignatureDoesNotMatch&source=PopGw",
    "HostId":"codeup.cn-hangzhou.aliyuncs.com",
    "Code":"SignatureDoesNotMatch"
}

检查 message 中的 stringToSign 与你计算出来的 stringToSign 是否一致,如果一致,检查计算 HMAC-SHA1 签名时用作 key 的 AccessKeySecret 是否正确。