签名认证
臻云极致的所有 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
至此,一个完整的步骤就完成了!