开发者社区> 问答> 正文

V3版API 签名机制是怎样的?


OpenSearch服务会对每个访问的请求进行身份验证,通过使用Access Key ID和Access Key Secret进行对称加密的方法来验证请求的发送者身份。Access Key ID和Access Key Secret由阿里云官方颁发给访问者(可以通过阿里云官方网站申请和管理),其中Access Key ID用于标识访问者的身份;
Access Key Secret是用于加密签名字符串和服务器端验证签名字符串的密钥,必须严格保密,只有阿里云和用户知道。

支持应用类型


V3 版API 支持对高级版及标准版应用进行操作

通信协议


只支持HTTP协议

请求方法


搜索需使用GET方式,推送数据需使用POST方式
也需要包含上面提到的这些相关的请求Header

Authorization 字段计算方法


需在 HTTP 请求 Header 头信息中增加 Authorization(授权)来包含签名(Signature)信息,表明该请求已被授权,请求Header 中也需要包含文档下面“签名示例”部分中“请求Header”中提到的这些相关的请求Header。
请求 Header 中包含的参数都必须要参与签名(例如 Content-Md5,Content-Type,Date,Http专有 Header 等等)。



按照RFC2104的定义,使用上面的用于签名的字符串计算签名HMAC值

  • 签名的方法用 RFC 2104 中定义的 HMAC-SHA1 方法
  • 签名的字符串必须为UTF-8格式
  • 含有中文字符的签名字符串必须先进行UTF-8编码,再与AccessKeySecret计算最终签名
  • 签名参数先后顺序,必须和上面保持一致
参数描述
AccessKeyId(查询或推送)不能为空,请求Header 中的 Authorization 需要用到该 AccessKeyId 值,表示访问指定应用的用户
AccessKeySecret(查询或推送)不能为空,签名所需的秘钥
VERB(查询或推送)不能为空,表示请求操作方法。HTTP 请求 Method,主要有 PUT、GET、POST、HEAD、DELETE 等,不同接口Method也不同
\n换行符
Content-MD5(推送)不能为空,表示请求内容数据的MD5值,对消息内容(不包括头部)计算 MD5 值获得 128 比特位数字,对该数字进行 base64 编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),例如4991ef0788236a8f280fed0db928e74e ,对于不发送 body 的请求,例如查询请求,此值请留空。详情参看RFC2616 Content-MD5
Content-Typeapplication/json
Date(查询或推送)不能为空,表示此次操作时间,且必须为[backcolor=transparent]秒级 的 ISO 格式,如“2017-08-09T01:54:12Z”,时间为UTC时间;如果此时间和 OpenSearch 服务器的时间差正负 15 分钟以上,服务器将拒绝该服务,并返回 HTTP 403 错误
CanonicalizedOpenSearchHeaders(查询)不能为空,用于区分每次请求,以 X-Opensearch- 为前缀的Http专有 Header组合,例如X-Opensearch-Nonce,在签名过程中这些Http专有 Header名必须全部小写,例如 x-opensearch-nonce,若这些Http专有Header是作为请求Header参数,则需按照原格式名显示若请求 Header 中不包含这些Http专有 Header,该参数不参与签名计算,在签名方法中直接去掉该参数。
CanonicalizedResource(查询或推送)不能为空,表示用户此次请求路径,例如/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=config%3Dformat%3Afulljson&&query%3Dname%3A%27%E6%96%87%E6%A1%A3%27&&sort%3Did


查询请求

请求签名参数必须请求 Header 参数必须
AccessKeySecretDate
VERBX-Opensearch-Nonce
DateAuthorization
x-opensearch-nonce
canonicalized_resource
  • Header 中的参数值必须要与对应签名方法中的参数值一致
  • 理论上 Content-Md5,Content-Type,Date,CanonicalizedOpenSearchHeaders,Authorization 这些参数都需要添加到请求Header中,只包含必须参数可能会出现报错,需避免
  • 请求 Header 中包含的参数都必须要参与签名


推送请求

请求签名参数必须请求 Header 参数必须
AccessKeySecretContent-MD5
VERBDate
Content-MD5Authorization
Date
canonicalized_resource
  • Header 中的参数值必须要与对应签名方法中的参数值一致
  • 理论上 Content-Md5,Content-Type,Date,CanonicalizedOpenSearchHeaders,Authorization 这些参数都需要添加到请求Header中,只包含必须参数可能会出现报错,需避免
  • 请求 Header 中包含的参数都必须要参与签名


构建CanonicalizedOpenSearchHeaders的方法


所有以 X-Opensearch- 为前缀的 Http专有 Header 被称为 CanonicalizedOpenSearchHeaders,其他非 Http专有 Header 将不被纳入验证

  1. 将所有以 X-Opensearch- 为前缀的Http专有 Header 对应的内容补齐,例如X-Opensearch-Nonce : 150224365226248(该Nonce参数值,可由10位时间戳+5位随机值(10000~99999)组合而成,例如150224365226248),再去除所有值为空的Http专有 Header

  2. 将这些有对应内容值的Http专有 Header 按照名称的字典序进行升序排序

  3. 再将这些排序后的专有 Header名,全部转换成小写字母,例如将 X-Opensearch-Nonce : 150224365226248转换成 x-opensearch-nonce : 150224365226248

  4. 删除请求头和内容之间分隔符两端出现的任何空格。例如该 x-opensearch-nonce : 150224365226248 参数,删除两端空格后为:x-opensearch-nonce:150224365226248

  5. 最后将每个请求头及对应内容作为一个单位项,再将每一项之间用 \n 连接拼成最后的 CanonicalizedOpenSearchHeaders,注意最后一个也要有 \n

[backcolor=transparent]注意:
  • 若查询请求Header中不包含此处Http专有 Header,即该参数中一个Http专有 Header都没有,则无需 \n,只需在签名方法中去掉该CanonicalizedOpenSearchHeaders签名参数即可,该参数不参与签名计算。
  • 将Http专有 Header添加到Header中时,不能是转换后的小写形式,需按原格式显示


构建CanonicalizedResource的方法

  • 签名的字符串必须为UTF-8格式,且含有中文字符的签名字符串必须先进行 UTF-8 编码,再与 AccessKeySecret 计算最终签名
  • 查询 CanonicalizedResource = path + ? + query
  • 推送 CanonicalizedResource = path


构建 path 部分


对 path 进行urlencode后,再替换 %2F 为 /,下面的app_schema_demo需替换为自己应用名,常见 path 如下所示
  • search查询path /v3/openapi/apps/app_schema_demo/search
  • suggest查询path /v3/openapi/apps/app_schema_demo/suggest/suggest/search
  • 最终查询指定应用信息查询请求串,下面“appid”需替换为待查询的应用ID,需包含Authorization授权签名参数(无需指定查询参数) /v3/openapi/apps/appid
  • 推送数据path(tab 是要推送到应用中的某个具体表名,也需替换为自己应用表名)/v3/openapi/apps/app_schema_demo/tab/actions/bulk


<a name="构建 query 部分
" class="reference-link" style="box-sizing: border-box; color: rgb(0, 193, 224); transition: color 0.2s; font-weight: inherit; background: 0px 0px;">构建 query 部分



query 部分由查询参数构成,参数为键值对形式
  1. 为需要指定的查询参数设置对应的参数值,并去掉value为空的参数(value为空的参数不计算签名)
  2. 再对每一个参数按照先比较参数名后比较参数值的顺序,按照字典升序
  3. 再对每一部分的参数名和参数值进行 urlencode,再将参数名和对应参数值之间通过=拼接
  4. 再将各个查询参数之间用 & 分割拼接并存储到 query 字符串中
  5. 再将该 query 字符串中的 + 字符,替换成 %20
  6. 最后按照 path + ? + query 方式拼接至CanonicalizedResource字符串中,即完成查询操作CanonicalizedResource参数构建,示例如下/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=config%3Dformat%3Afulljson&&query%3Dname%3A%27%E6%96%87%E6%A1%A3%27&&sort%3Did

[backcolor=transparent]注意:
  • query参数中各个查询子句之间必须要用 && 进行拼接
  • 若为推送操作,则只需将 path 部分拼接至 CanonicalizedResource 字符串中即可


构建 Authorization 字段


构建方法参考开头部分描述,需添加到请求 Header 中
  • 假如AccessKeyId 为LTAIvDPtKBhpSPki,Signature为 1iAIX7FA8Ej4//m2DIVAPWIsVEc=,python3示例代码如下

  1. [backcolor=transparent]headers[backcolor=transparent][[backcolor=transparent]'Authorization'[backcolor=transparent]][backcolor=transparent] [backcolor=transparent]=[backcolor=transparent] [backcolor=transparent]'OPENSEARCH '[backcolor=transparent] [backcolor=transparent]+[backcolor=transparent] [backcolor=transparent]'LTAIvDPtKBhpSPki'[backcolor=transparent] [backcolor=transparent]+[backcolor=transparent] [backcolor=transparent]':'[backcolor=transparent] [backcolor=transparent]+[backcolor=transparent] [backcolor=transparent]'1iAIX7FA8Ej4//m2DIVAPWIsVEc='[backcolor=transparent].[backcolor=transparent]decode[backcolor=transparent]([backcolor=transparent]'utf-8'[backcolor=transparent])


签名示例


假如参数值如下
  • Authorization值为OPENSEARCH LTAIvDPtKBhpSPki:DzhOHAOO+vmlBzHR2ApD/3Hpyhc=
  • AccessKeySecret值为 5OCGljiVeXLvO49QaEYuYQjUb1HAZQ
  • 请求方式为GET
  • Content-MD5值为空,此处作为查询请求
  • Content-Type值为application/json
  • Date值为2017-08-09T01:54:12Z
  • CanonicalizedOpenSearchHeaders值为x-opensearch-nonce:150224365226248
  • CanonicalizedResource值为/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=config%3Dformat%3Afulljson&&query%3Dname%3A%27%E6%96%87%E6%A1%A3%27&&sort%3Did
请求Header签名字符串计算公式签名字符串
‘Content-MD5’: ‘’,‘Content-Type’: ‘application/json’,‘Authorization’: ‘OPENSEARCH LTAIvDPtKBhpSPki:DzhOHAOO+vmlBzHR2ApD/3Hpyhc=’,‘X-Opensearch-Nonce’: ‘150224365226248’,‘Date’: ‘2017-08-09T01:54:12Z’Signature = base64(hmac-sha1(AccessKeySecret,VERB + “\n”+ Content-Md5 + “\n”+ Content-Type + “\n”+ Date + “\n”+ CanonicalizedOpenSearchHeaders+ CanonicalizedResource))5OCGljiVeXLvO49QaEYuYQjUb1HAZQ ,GET\n\napplication/json\n2017-08-09T01:54:12Z\nx-opensearch-nonce:150224365226248\n/v3/openapi/apps/app_schema_demo/search?fetch_fields=name&query=config%3Dformat%3Afulljson&&query%3Dname%3A%27%E6%96%87%E6%A1%A3%27&&sort%3Did

[backcolor=transparent]注意:
  • 请求Header中参数值需与签名方法中对应参数值保持一致


可用以下方法计算签名(Signature)

  • 以 hash_hmac 和 base64_encode 编码生成加密值作为Signature

python3 示例代码:


假如AccessKeySecret值为 5OCGljiVeXLvO49QaEYuYQjUb1HAZQ 那么通过上面的签名方法构造出来的签名值为DzhOHAOO+vmlBzHR2ApD/3Hpyhc=

构建请求串


请求串 = host + CanonicalizedResource
需在 HTTP 请求 Header 头信息中增加 Authorization(授权)来包含签名(Signature)信息,表明该请求已被授权,同时Header中也需要包含上面提到的这些相关的请求Header。(host为应用访问API地址)

v3api签名Demo(python)


目前已对外公开 v3版官方Java SDK 和 PHP SDK,且PHP SDK已包含v3api签名过程实现源码,直接调用这些方法即可使用,也可参考 PHP SDK 签名实现过程源码,或参考本文档v3api签名过程来实现其它语言SDK。
因目前官方暂未提供python版 SDK,为方便用户参考实现该文档描述签名过程,此处提供 python 查询签名Demo,以供用户参考实现本文档签名操作
【特别注意】
  • 此处提供 Demo 仅供参考使用,后续用户参考此Demo实现的 SDK 由用户自己维护
  • 使用 C# 语言实现本文档中v3版api鉴权,经过测试确认会有问题,在设置请求Header中的Date参数时,该Date参数值无法设置成符合我们规定的时间格式内容,.NET框架中强制指定了该请求Header中的Date参数为时间类型,不能为字符串类型(因此C#用户需考虑通过其它语言来实现v3版api查询及推送操作鉴权功能,或通过其它脚本语言实现v3版api查询及推送操作鉴权功能,再将该功能嵌入C#中,通过调用该嵌入功能来实现查询及推送操作)

展开
收起
轩墨 2017-10-25 11:48:47 2929 0
0 条回答
写回答
取消 提交回答
问答排行榜
最热
最新

相关电子书

更多
Spring Boot2.0实战Redis分布式缓存 立即下载
CUDA MATH API 立即下载
API PLAYBOOK 立即下载