函数计算产品提供的API采用ROA签名风格,本文介绍V3版本的签名机制,更多信息,请参见V3版本请求体&签名机制。
签名机制
采用AK/SK方式进行签名与认证。对于每一次HTTP或HTTPS协议请求,阿里云API网关将依据请求参数信息重新计算签名,通过对比该签名与请求中提供的签名是否一致,从而验证请求者的身份,以确保传输数据的完整性与安全性。
请求及返回结果都使用UTF-8字符集进行编码。
步骤一:构造规范化请求
构造规范化请求(CanonicalRequest)的伪代码如下:
CanonicalRequest =
HTTPRequestMethod + '\n' + // http请求方法,全大写
CanonicalURI + '\n' + // 规范化URI
CanonicalQueryString + '\n' + // 规范化查询字符串
CanonicalHeaders + '\n' + // 规范化消息头
SignedHeaders + '\n' + // 已签名消息头
HashedRequestPayload // RequestBody经过hash处理后的值
HTTPRequestMethod(请求方法)
即大写的HTTP方法名,如GET、POST。
CanonicalURI(规范化URI)
URL的资源路径部分经过编码之后的结果。资源路径部分指URL中host与查询字符串之间的部分,包含host之后的/但不包含查询字符串前的?。用户发起请求时的URI应使用规范化URI,编码方式使用UTF-8字符集按照RFC3986的规则对URI中的每一部分(即被/分割开的字符串)进行编码:
-
字符A~Z、a~z、0~9以及字符
-、_、.、~不编码。其他字符编码成
%加字符对应ASCII码的16进制。示例:半角双引号(")对应%22。需要注意的是,部分特殊字符需要特殊处理,具体如下:编码前
编码后
空格( )
%20星号(
*)%2A%7E波浪号(
~)
如果您使用的是Java标准库中的java.net.URLEncoder,可以先用标准库中encode编码,随后将编码后的字符中加号(+)替为%20、星号(*)替换为%2A、%7E替换为波浪号(~),即可得到上述规则描述的编码字符串。
RPC风格API使用正斜杠(/)作为CanonicalURI,
ROA风格API该参数为OpenAPI元数据中path的值,例如/api/v1/clusters。
CanonicalQueryString(规范化查询字符串)
在OpenAPI元数据中,如果API的请求参数信息包含了"in":"query"时,需要将这些请求参数按照如下构造方法拼接起来:
-
将请求参数按照参数名称的字符顺序升序排列。
-
使用UTF-8字符集按照RFC3986的规则对每个参数的参数名称和参数值分别进行URI编码,具体规则与上一节中的CanonicalURI编码规则相同。
-
使用等号(
=)连接编码后的请求参数名称和参数值。当参数没有值时,应使用空字符串作为该参数的值。 -
多个请求参数之间使用与号(
&)连接。
-
当请求参数是JSON字符串类型时,JSON字符串中的参数顺序不会影响签名计算。
-
当无查询字符串时,使用空字符串作为规范化查询字符串。
示例值:
ImageId=win2019_1809_x64_dtc_zh-cn_40G_alibase_20230811.vhd&RegionId=cn-shanghai
HashedRequestPayload
RequestBody经过Hash摘要处理后再进行Base16编码得到HashedRequestPayload,并将RequestHeader中x-acs-content-sha256的值更新为HashedRequestPayload的值。伪代码如下:
HashedRequestPayload = HexEncode(Hash(RequestBody))
-
在OpenAPI元数据中,如果API的请求参数信息包含了
"in": "body"或"in": "formData"时,需通过RequestBody传递参数:说明若无请求参数通过RequestBody传递时,RequestBody的值固定为一个空字符串。
-
当请求参数信息包含
"in": "formData"时,参数需按照key1=value1&key2=value2&key3=value3拼接成字符串,同时,需在RequestHeader中添加content-type=application/x-www-form-urlencoded。需要注意的是,当请求参数类型是array、object时,需要将参数值转化为带索引的键值对。 -
当请求参数信息包含
"in": "body"时,需要在RequestHeader中添加content-type,content-type的值与请求内容类型有关。例如:-
请求内容类型为JSON数据时,content-type的值为
application/json。 -
请求内容类型为二进制文件流时,content-type的值为
application/octet-stream。
-
-
-
Hash表示消息摘要函数,目前仅支持SHA256算法。
-
HexEncode表示以小写的十六进制的形式返回摘要的编码函数(即Base16编码)。
当RequestBody为空时,HashedRequestPayload的示例值:
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
CanonicalHeaders(规范化请求头)
将RequestHeader中的参数按照如下构造方法拼接起来:
-
过滤出RequestHeader中包含以
x-acs-为前缀、host、content-type的参数。 -
将参数的名称转换为小写,并按照字符顺序升序排列。
-
将参数的值去除首尾空格。
-
将参数名称和参数值以英文冒号(
:)连接,并在尾部添加换行符(\n),组成一个规范化消息头(CanonicalHeaderEntry)。 -
将多个规范化消息头(CanonicalHeaderEntry)拼接成一个字符串。
除Authorization外的所有RequestHeader,只要符合要求都必须被加入签名。
伪代码如下:
CanonicalHeaderEntry = Lowercase(HeaderName) + ':' + Trim(HeaderValue) + '\n'
CanonicalHeaders =
CanonicalHeaderEntry0 + CanonicalHeaderEntry1 + ... + CanonicalHeaderEntryN
示例值:
host:ecs.cn-shanghai.aliyuncs.com
x-acs-action:RunInstances
x-acs-content-sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
x-acs-date:2023-10-26T10:22:32Z
x-acs-signature-nonce:3156853299f313e23d1673dc12e1703d
x-acs-version:2014-05-26
SignedHeaders(已签名消息头列表)
用于说明此次请求中参与签名的公共请求头信息,与CanonicalHeaders中的参数名称一一对应。其构造方法如下:
-
将CanonicalHeaders中包含的请求头的名称转为小写。
-
按首字母升序排列并以英文分号(
;)分隔。伪代码如下:
SignedHeaders = Lowercase(HeaderName0) + ';' + Lowercase(HeaderName1) + ... + Lowercase(HeaderNameN)
示例值:
host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version
步骤二:构造待签名字符串
按照以下伪代码构造待签名字符串(stringToSign):
StringToSign =
SignatureAlgorithm + '\n' +
HashedCanonicalRequest
-
SignatureAlgorithm
签名协议目前仅支持ACS3-HMAC-SHA256算法。
-
HashedCanonicalRequest
规范化请求摘要串,计算方法伪代码如下:
HashedCanonicalRequest = HexEncode(Hash(CanonicalRequest))-
Hash表示消息摘要函数,目前仅支持SHA256算法。
-
HexEncode表示以小写的十六进制的形式返回摘要的编码函数(即Base16编码)。
-
示例值:
ACS3-HMAC-SHA256
7ea06492da5221eba5297e897ce16e55f964061054b7695beedaac1145b1e259
步骤三:计算签名
按照以下伪代码计算签名值(Signature)。
Signature = HexEncode(SignatureMethod(Secret, StringToSign))
-
StringToSign:步骤二中构造的待签名字符串,UTF-8编码。
-
SignatureMethod:使用HMAC-SHA256作为签名算法。
-
Secret:AccessKey Secret。
-
HexEncode:以小写的十六进制的形式返回摘要的编码函数(即Base16编码)。
示例值:
06563a9e1b43f5dfe96b81484da74bceab24a1d853912eee15083a6f0f3283c0
步骤四:将签名添加到请求中
计算完签名后,构造Authorization请求头,格式为:Authorization:<SignatureAlgorithm> Credential=<AccessKeyId>,SignedHeaders=<SignedHeaders>,Signature=<Signature>。
示例值:
ACS3-HMAC-SHA256 Credential=YourAccessKeyId,SignedHeaders=host;x-acs-action;x-acs-content-sha256;x-acs-date;x-acs-signature-nonce;x-acs-version,Signature=06563a9e1b43f5dfe96b81484da74bceab24a1d853912eee15083a6f0f3283c0