签名认证
臻云极致的所有 RESTful 接口都使用AccessKeyId及AccessKeySecret对称加密的方法来验证某个请求的发送者身份。AccessKeyId用于标示用户;AccessKeySecret是用户用于加密签名字符串和服务器用来验证签名字符串的密钥,且AccessKeySecret必须妥善保管。
当用户想以个人身份向服务器发送请求时,首先需要将发送的请求按照指定的格式生成待签名的字符串;然后使用AccessKeySecret对待签名的字符串进行加密产生签名字符串。服务器收到请求以后,会通过AccessKeyId找到对应的AccessKeySecret,以同样的方法计算签名字符串,然后与请求的签名字符串比较,如果计算出来的签名字符串和请求的一样即认为该请求是有效的;否则,服务器将拒绝处理这次请求,并返回错误。
获取AccessKey
登录臻云极致(https://open.vzicloud.com),选择左侧导航栏AccessKey菜单,如下图所示:
点击创建按钮即可打开创建AccessKey对话框,如下图:
选择过期时间,点击确定即可创建AccessKey。
注意事项:
- 您可以选择大于当前时间的任何过期时间,但创建后,该AccessKey的过期时间将不可修改且在过期时间之前有效。
- 若该AccessKey过期,请重新创建并更换新的AccessKey。
- 请务必妥善保管此AccessKey(建议不要将AccessKeySecret写在网页前端代码里),若此AccessKey不小心泄露,您可以在AccessKey页面禁用或者删除此AccessKey,如下图所示:

签名实现
您可以选择使用臻识提供的签名示例代码完成签名请求,也可以选择根据下面的描述自主开发完成签名。
示例代码
各语言版本的使用说明见示例代码README.md文件。
URL签名示例
以绑定设备接口为例:
POST https://open.vzicloud.com/openapi/v1/stp/user/devices?expires=1600689938&accesskey_id=7e9peQ8C1125A7Cz4LVFJl61jxFtHs0F&signature=eS9S3sbaWaBLRL8HB9AF5ZZNUu4%3D HTTP/1.1
Host: open.vzicloud.com
Content-Length: 91
Content-Type: application/json
[{"sn":"12345678-87654321","group_id":0,"username":"admin","password":"admin","remark":""}]
其中,必须至少包含expires、accesskey_id、signature这三个参数,除此之外根据不同的接口做相应的变化。
- expires: 这个参数的值是一个UNIX时间(自UTC时间1970年1月1号开始的秒数),用于标识该URL的超时时间。如果服务器接收到这个URL请求的时候晚于签名中包含的
expires参数时,则返回请求超时的错误。为了安全起见,请尽可能设置一个较短的过期时间,比如10分钟。注意:请确保您的计算机已同步正确的北京时间。 - accesskey_id: 即
AccessKeyId。 - signature: 表示签名字符串。
signature计算方式
signature = urlencode(base64(hmac-sha1(AccessKeySecret,
VERB + "\n"
+ CONTENT-MD5 + "\n"
+ CONTENT-TYPE + "\n"
+ EXPIRES + "\n"
+ CanonicalizedResource)))
- AccessKeySecret: 表示签名所需要的密钥。
- VERB: 表示
HTTP请求的方法,主要有GET、POST、PUT、DELETE等,注意必须是大写。 - \n: 表示换行符。
- CONTENT-MD5: 表示请求内容数据(特指HTTP请求的Body)的
MD5值,对消息内容(不包括头部)计算MD5值获得128比特位数字,对该数字进行base64编码而得到。该请求头可用于消息合法性的检查(消息内容是否与发送时一致),如”eB5eJF1ptWaXm4bijSPyxw==”,如果请求中没有数据(HTTP请求没有Body),则这个值为空。详情请参见RFC2616 Content-MD5。 - CONTENT-TYPE: 表示请求内容的类型,如”
application/json”,如果请求中没有数据(HTTP请求没有Body),则这个值为空,如果请求中携带了数据,则一定要携带这个值。 - EXPIRES: 与上面的
expires一样。 - CanonicalizedResource: 表示用户想要访问的资源。
其中有几点规则需要注意:
- 签名的字符串必须为
UTF-8格式。含有中文字符的签名字符串必须先进行UTF-8编码,再与AccessKeySecret计算最终签名。 - 签名的方法用RFC 2104中定义的
HMAC-SHA1方法,其中Key为AccessKeySecret。 - 服务器先验证请求时间是否晚于expires时间,然后再验证签名。
- 将签名字符串放到
URL时,注意要对URL进行urlencode。
构建CanonicalizedResource的方式
用户发送请求中想访问的服务器目标资源被称为CanonicalizedResource。它的构建方法如下:
- 将
CanonicalizedResource置成空字符串; - 放入要访问的资源(也就是
URL里面的Path部分,针对上面的签名示例,就是/openapi/v1/stp/user/devices); - 如果用户请求
URL包含了参数(QueryString,也叫Http Request Parameters),先在CanonicalizedResource字符串尾添加?,然后再将这些参数名按照字典序,从小到大排列,以&为分隔符,按顺序添加到CanonicalizedResource中,其中要注意几点:- 如果没有包含参数,不需要添加
?。 - 注意参数名的大小写问题。
signature,expires,accesskey_id这三个参数不包含在内,signature很好理解,因为此时签名还没计算出来,特别注意的是expires、accesskey_id。- 注意,此时不要对参数值进行
urlencode。
- 如果没有包含参数,不需要添加
针对上面的示例,完整的CanonicalizedResource为: /openapi/v1/stp/user/devices ,此示例中并没有请求参数,假如有三个参数name=名称&age=20&id=1的话,那么此时,完整的CanonicalizedResource为:/openapi/v1/stp/user/devices?age=20&id=1&name=名称。
完整演示
针对前面的示例,接下来演示整个计算步骤:
0. 前置条件
- 本示例中,约定AccessKey如下:
- AccessKeyId:
7e9peQ8C1125A7Cz4LVFJl61jxFtHs0F - AccessKeySecret:
ZfATtI0jK9uclIEwcHJ7JLAj7rRX1mgY
- AccessKeyId:
- 本示例中,约定
expires为:1600689938 - 本示例中的
Body Data采用紧凑型的Json格式。
1. 计算CONTENT-MD5
Body Data为[{"sn":"12345678-87654321","group_id":0,"username":"admin","password":"admin","remark":""}]- 按照上面
CONTENT-MD5相关说明计算出结果为:vrjt79DVzdoDc55z64BrhA==
2. 计算CanonicalizedResource
- 针对以上示例,要访问的资源为:
/openapi/v1/stp/user/devices - 由于没有其他参数,所以最终结果为:
/openapi/v1/stp/user/devices
3. 计算CanonicalString
CanonicalString为将要加密的字符串,格式为:
VERB + "\n"
+ CONTENT-MD5 + "\n"
+ CONTENT-TYPE + "\n"
+ EXPIRES + "\n"
+ CanonicalizedResource
针对这个格式及以上计算出的结果,可以拼接出CanonicalString为:
POST\nvrjt79DVzdoDc55z64BrhA==\napplication/json\n1600689938\n/openapi/v1/stp/user/devices
注意:上面的 \n 是换行符,而不是字符串。
4. 计算signature
- 将
CanonicalString转换为UTF-8编码,然后进行HmacSHA1加密,再进行Base64编码,得到结果为:eS9S3sbaWaBLRL8HB9AF5ZZNUu4=
5. 生成完成的URL
针对以上计算的结果,我们可以生成一个完整的URL,注意针对每一个参数值要进行URL编码,最终结果如下:
https://open.vzicloud.com/openapi/v1/stp/user/devices?expires=1600689938&accesskey_id=7e9peQ8C1125A7Cz4LVFJl61jxFtHs0F&signature=eS9S3sbaWaBLRL8HB9AF5ZZNUu4%3D
至此,一个完整的步骤就完成了!