V2版本ROA风格请求体&签名机制
本文介绍了阿里云 OpenAPI 的 ROA风格接口,包括ROA OpenAPI 请求的组成部分,如何通过这些组成部分构造一个 OpenAPI 请求,如何获取返回结果以及签名机制等。阿里云 ROA OpenAPI 向开发者提供HTTP接口,如果您想要自研阿里云ROA调用风格的OpenAPI SDK,您可以参看本文,来构造 HTTP 请求调用对应的 OpenAPI 。
不再推荐使用该访问方式,请移步参考V3版本请求体&签名机制。
HTTP 请求结构
一个完整的阿里云 OpenAPI 请求,包含以下部分。
名称 | 是否必选 | 描述 | 示例值 |
协议 | 是 | 您可以查阅不同云产品的 API 参考文档进行配置。支持通过 | https:// |
服务地址 | 是 | 即 Endpoint。您可以查阅不同云产品的服务接入地址文档,查阅不同服务区域下的服务地址。 | cs.aliyuncs.com |
resource_URI_parameters | 是 | 接口URL,包括接口路径和位置在 path、 query的接口请求参数。 | /clusters/{cluster_id}/triggers |
RequestHeader | 是 | 请求头信息,通常包含API的版本、Host、Authorization等信息。后文将详细说明,请参见RequestHeader(请求头) | x-acs-action |
RequestBody | 是 | 定义在 body 中的业务请求参数,建议您在阿里云 OpenAPI 开发者门户进行试用。 | cluster_id |
HTTPMethod | 是 | 请求使用的方法,ROA接口请求方法包括PUT、POST、GET、DELETE。 | POST |
RequestHeader(请求头)
一个完整的阿里云 OpenAPI 请求,包含以下部分。
名称 | 类型 | 是否必选 | 描述 | 示例值 |
x-acs-action | String | 是 | API的名称。您可以访问阿里云 OpenAPI 开发者门户,搜索您想调用的 OpenAPI | CreateTrigger |
x-acs-version | String | 是 | API 版本。您可以访问阿里云 OpenAPI 开发者门户,查看您调用 OpenAPI 对应的 API 版本 | 2015-12-15 |
Accept | String | 否 | 指定接口返回数据的格式。ROA 只支持固定值 | application/json |
Authorization | String | 非匿名请求必须 | 用于验证请求合法性的认证信息,格式为 Signature为请求签名,取值参见签名机制。 | acs testid:D9uFJAJgLL+dryjBfQK+YeqGtoY= |
x-acs-signature-nonce | String | 否 | 签名唯一随机数。用于防止网络重放攻击,建议您每次请求都使用不同的随机数。 | 15215528852396 |
Date | String | 是 | 当前时间戳,有效期为15分钟,即生成时间戳后需要在15分钟内发起请求。HTTP 1.1协议中规定的 GMT 时间,例如:Tue 9 Apr 2019 07:35:29 GMT。 | Tue 9 Apr 2022 07:35:29 GMT |
x-acs-signature-method | String | 非匿名请求必须 | 签名方式。目前为固定值 | HMAC-SHA1 |
Content-MD5 | String | 否 | HTTP请求正文的128-bit MD5散列值转换成BASE64编码的结果。 | Gtl/0jNYHf8t9Lq8Xlpaqw== |
Host | String | 是 | 即服务地址,参见HTTP 请求结构。 | cs.aliyuncs.com |
接口请求构造
一个完整的接口请求构造如下:
HTTPMethod /resource_URI_parameters
RequestHeader
RequestBody
请求参数由公共请求头和API自定义参数组成。公共请求头中包含API版本号、身份验证等信息。
HTTPMethod :请求使用的方法,包括PUT、POST、GET、DELETE。详情请参看HTTP 请求结构。
resource_URI_parameters:请求要调用的资源标识符,如
/cluster
。详情请参看HTTP 请求结构。RequestHeader:请求头信息,通常包含API的版本、Host、Authorization等信息。详情请参看HTTP 请求结构。
RequestBody:在 body 中的业务请求参数。详情请参看HTTP 请求结构。
示例:
POST /clusters/test_cluster_id/triggers HTTP/1.1
{
"x-acs-action":"CreateTrigger",
"x-acs-version":"2015-12-15",
"Accept":"application/json",
"Authorization": "acs testid:D9uFJAJgLL+dryjBfQK+YeqGtoY=",
"x-acs-signature-nonce":"15215528852396",
"Date":"Tue 9 Apr 2022 07:35:29 GMT",
"x-acs-signature-method":"HMAC-SHA1",
"Content-MD5":"Gtl/0jNYHf8t9Lq8Xlpaqw=="
"Host":"cs.aliyuncs.com"
}
{
"cluster_id":"test_cluster_id",
"project_id":"default/nginx-test",
"action":"redeploy",
"type":"deployment"
}
请求编码
请求及返回结果都使用UTF-8字符集进行编码。
接口返回结果
每次接口调用请求,无论成功与否,系统都会返回一个唯一识别码RequestId。调用API服务后返回数据采用统一格式。接口调用成功后,会返回接口的返回参数请求 ID,HTTP 状态码为 2xx(不显示在响应正文中)。响应正文示例如下:
{
"RequestId": "4C467B38-3910-447D-87BC-AC049166F216"/* 返回结果数据 */
}
接口调用出错后,会返回请求ID、服务节点、错误码和错误信息,HTTP 状态码为 4xx 或者 5xx。示例如下:
{
"code": "400", /* 错误码 */
"message": "Cluster permission denied", /* 错误信息 */
"requestId": "A026BC61-0523-5A6D-A5F3-314A3D92FD50", /* 请求 ID */
"status": 400 /* 业务字段 */
}
接口调用出错后,您可以根据返回的RequestId,在阿里云OpenAPI开发者门户-诊断中排查。此外,您还可以查阅公共错误码以及API 错误中心。当您无法排查错误时,可以提交工单,并在工单中注明Host(服务地址,参见HTTP 请求结构)和RequestId。
签名机制
为保证API的安全调用,在调用API时阿里云会对每个API请求通过签名(Signature)进行身份验证。无论使用HTTP还是HTTPS协议提交请求,都需要在请求中包含签名信息。本文指导您如何进行签名处理。
对于每一次HTTP或者HTTPS协议请求,阿里云会根据访问中的签名信息验证访问请求者身份。您在访问时签名信息时,请按照以下方法对请求进行签名处理:
步骤一:构造规范化请求头
阿里云规范化请求头(CanonicalizedHeaders)是非标准HTTP头部信息。它是指请求中出现的以x-acs-
为前缀的参数信息,构造方法如下:
将所有以
x-acs-
为前缀的HTTP请求头的名称转换成小写字母。如X-acs-Meta-Name: TaoBao
转换成x-acs-meta-name: TaoBao
。阿里云规范请求头的名称大小写不敏感,建议全小写。如果一个公共请求头的值过长,则需要处理其中的
\t
、\n
、\r
、\f
分隔符,将其替换成英文半角的空格。将上一步得到的所有HTTP阿里云规范头按照字典顺序进行升序排列。
删除请求头的名称和值之间的分隔符两端出现的任何空格。例如
x-acs-oss-meta-name :TaoBao,Alipay
转换成x-acs-oss-meta-name:TaoBao,Alipay
。在每一个请求头后添加一个
\n
分隔符(包括最后一个请求头),然后将所有请求头拼接在一起即获得CanonicalizedHeaders。
步骤二:构造规范化资源
规范化资源(CanonicalizedResource) 表示您想要访问资源的规范描述,具体构造方式如下:
将请求的查询字符串(queryString)中的参数按照参数名称的字典序重新排序,并以
&
分隔符连接生成已排序查询字符串。将请求资源路径(指URL中host与查询字符串之间的部分,包含host之后的
/
但不包含查询字符串前的?
)与已排序查询字符串以?
拼接,得到规范化资源。当查询字符串不存在时,直接用请求资源路径作为规范化资源。
示例
原始请求URL:
http://demo-product.aliyuncs.com/instances?status=ONLINE&group=test_group
规范化资源:
/instances?group=test_group&status=ONLINE
步骤三:构造待签名字符串
按照以下伪代码构造待签名字符串(stringToSign):
String stringToSign =
HTTPMethod + "\n" +
Accept + "\n" +
ContentMD5 + "\n" +
ContentType + "\n" +
Date + "\n" +
CanonicalizedHeaders +
CanonicalizedResource
参数 | 描述 |
HTTPMethod | 大写的HTTP方法名,例如POST、GET。 |
Accept | Accept请求头的值,当请求头不存在时,使用空字符串代替。 |
ContentMD5 | Content-MD5请求头的值,当请求头不存在时,使用空字符串代替。 |
ContentType | Content-Type请求头的值,当请求头不存在时,使用空字符串代替。 |
Date | Date请求头的值。 |
CanonicalizedHeaders | 步骤一:构造规范化请求头中获得的规范化请求头。 |
CanonicalizedResource | 步骤二:构造规范化资源中获得的规范化资源。 |
步骤四:计算签名
根据RFC2104的定义,按照HMAC-SHA1算法对上一步生成的待签名字符串进行签名计算,并以Base64编码规则将计算结果编码成字符串,即得到最终的签名值(signature)。
String signature = Base64(HMAC_SHA1(SigningKey, stringToSign))
计算签名时使用的SigningKey值就是您的AccessKey Secret。更多信息,请参见创建AccessKey。
步骤五:将签名添加到请求中
计算出签名结果 signature后,按照以下规则拼接字符串,并将结果作为 Authorization 请求头的值。
String Authorization = "acs " + AccessKeyId + ":" + signature
签名示例
本示例以调用 容器服务Kubernetes版(CS) CreateTrigger为应用创建触发器为例。假设您获得了AccessKeyID 为 testid, AccessKeySecret 为 testsecret,x-acs-signature-nonce 为 15215528852396,Date 为 Tue 9 Apr 2022 07:35:29 GMT。签名流程如下:
构造规范化请求头。
x-acs-signature-method:HMAC-SHA1
x-acs-signature-nonce:15215528852396
x-acs-signature-version:1.0
x-acs-version:2015-12-15
构造规范化资源。
/clusters/test_cluster_id/triggers
构造待签名字符串。
POST
application/json
Gtl/0jNYHf8t9Lq8Xlpaqw==
application/json
Tue 9 Apr 2022 07:35:29 GMT
x-acs-signature-method:HMAC-SHA1
x-acs-signature-nonce:15215528852396
x-acs-signature-version:1.0
x-acs-version:2015-12-15
/clusters/test_cluster_id/triggers
计算签名。
acs testid:D9uFJAJgLL+dryjBfQK+YeqGtoY=
将签名添加到请求中。
POST /clusters/test_cluster_id/triggers HTTP/1.1
/* headers */
{
"accept": "application/json",
"date": "Tue 9 Apr 2022 07:35:29 GMT",
"host": "cs.cn-hangzhou.aliyuncs.com",
"x-acs-signature-nonce": "15215528852396",
"x-acs-signature-method": "HMAC-SHA1",
"x-acs-signature-version": "1.0",
"x-acs-version": "2015-12-15",
"content-type": "application/json",
"content-md5": "Gtl/0jNYHf8t9Lq8Xlpaqw==",
"authorization": "acs testid:D9uFJAJgLL+dryjBfQK+YeqGtoY="
}
/* body */
{
"project_id": "default/nginx-test",
"cluster_id": "test_cluster_id",
"action": "redeploy",
"type": "deployment"
}