上传回调(callback)是OSS的一个重要功能,可以应用在客户端与服务器端数据同步等一些场景。上传回调功能支持在回调的body中传入信息,但是在一些场景下,用户希望能够在回调给应用服务器的请求header中传入自定义的header,用于满足服务器端的一些特殊需求。因此OSS在callback现有功能基础上支持了自定义header,并加强了签名算法,将header加入了签名中,支持v2版本签名,增强了安全性。
如果对上传回调功能不了解,请先阅读此文档https://help.aliyun.com/document_detail/31989.html?spm=5176.doc31853.2.5.2lI4WS
一、传入参数的变化
callback功能是通过x-oss-callback这个header传入的参数来指定。这个header的value格式详细参考https://help.aliyun.com/document_detail/31989.html?spm=5176.doc31853.2.5.2lI4WS,在这个结构基础上,新增了两个字段,用于支持自定义header和v2版本签名。详细介绍如下:
字段 |
说明 |
示例 |
signatureVersion |
可选,默认值是“1.0”。目前支持的值是“1.0”和“2.0”,“1.0”指默认的签名算法,“2.0”指本文描述的签名算法 |
"signatureVersion" : "2.0" |
additionalHeaders |
可选,是一个map,表示OSS回调给用户的自定义header,除了“x-oss-”开头的header以及额外保留的header外,其余header都可以传递,最大支持10个自定义header,自定义header的key只允许数字横杠以及小写字母。保留的header如下: Content-Type Content-Length Host Authorization User-Agent Content-Md5 Expect Upgrade Keep-Alive |
"additionalHeaders" : { "my-header" : "abc", "any-header" : "abc" } |
下面是一个完整的例子:
{ "callbackUrl" : "www.test.com", "callbackHost" : "www.test.com", "callbackBodyType" : "application/x-www-form-urlencoded", "callbackBody" : "just for test", "signatureVersion" : "2.0", "additionalHeaders" : { "my-header" : "abc", "any-header" : "def" } } |
二、接收到的请求的变化
如果指定了自定义header以及v2版本签名,应用服务器接收到的请求中以下header将会增加或者变动:
header |
说明 |
示例 |
用户指定的自定义header |
用户通过additionalHeaders字段指定的header都会体现在回调请求中 |
“my-header”:”abc” “any-header”:”def” |
x-oss-additional-headers |
这个字段的内容是用户传入的自定义header的key列表,以逗号分隔 |
x-oss-additional-headers:any-header,my-header |
x-oss-signature-version |
默认是”1.0”,如果指定用v2版本签名,值会相应的变为”2.0” |
x-oss-signature-version:2.0 |
比如上例的callback请求,应用服务器将会收到以下POST请求:
POST / HTTP/1.1 Host: www.test.com Connection: close Content-Length: 13 any-header: def Authorization: PN7y979+gYNtSdJzEhdYnz/GCSUFF1L/SY6a6kvdy326A2JDryBjZj4sbAq3JVjTydngi4CihGfrq0V7pzZJKQ== Content-MD5: /ddPByElLVc6RX1St8jL+Q== Content-Type: application/x-www-form-urlencoded Date: Tue, 31 Oct 2017 01:58:58 GMT my-header: abc User-Agent: aliyun-oss-callback x-oss-additional-headers: any-header,my-header x-oss-bucket: guoping-file x-oss-owner: 1517986058650554 x-oss-pub-key-url: aHR0cHM6Ly9nb3NzcHVibGljLmFsaWNkbi5jb20vY2FsbGJhY2tfcHViX2tleV92MS5wZW0= x-oss-request-id: 59F7D8E12084A5D5E8F5EA92 x-oss-requester: 1517986058650554 x-oss-signature-version: 2.0 x-oss-tag: CALLBACK
just for test |
三、v2版本签名算法
v1版本的签名算法只是将uri和body加到了签名中,由于OSS本身会传递一些以x-oss-开头的header,而且用户可能会自定义一些header,都需要加入到签名中,因此oss支持了v2版本的签名。v2版本签名算法与v1版本唯一不同的地方是待签名字符串的组织方式不一样,其他比如使用RSA算法都保持一致。
v2版本待签名字符串的组织方式如下:
StrToSign = “POST” + “\n” + Content-MD5 + “\n” + Content-Type + “\n” + Date + “\n” + headers + uri + queryString |
注:
1、Content-Md5。即Content-MD5头的值,比如上例为” /ddPByElLVc6RX1St8jL+Q==”,这个header按照标准的协议生成,可以用于验证body是否被篡改,因此v2版本的签名将此header签进去,并不再将body签进去。
2、Content-Type。即Content-Type头的值,上例为” application/x-www-form-urlencoded”
3、Date。即Date头的值,上例为” Tue, 31 Oct 2017 01:58:58 GMT”。
4、headers。包括用户自定义的header以及x-oss-开头的header。包括两个部分:
1) 由自定义header以及x-oss-开头的header按照key的小写字典序排列的key value对,按照ToLower(key) + “:” + value + “\n”的方式一一加入到待签名字符串中。
2) 自定义header的key按照字典序排列后用”;”连接,最后再加上”\n”后加入到待签名字符串中。
5、uri。即回调的uri,需要注意的是需要做url编码。
6、queryString。将请求参数按照字典序排列,然后按照UrlEncode(key) + “=” + UrlEncode(value)的方式组织成一个单元,每一个单元再用”&”连接后,加入到”?”后面组成一个新的字符串,需要注意的是,如果请求参数中的key有重复,需要将重复的key和value都添加到待签名字符串中。如果没有请求参数,则不需要加此项
生成待签名字符串后,剩下的就与v1版本相同,即authorization = base64_encode(rsa_sign(private_key, StrToSign, md5)),生成的签名与v1版本一样放在authorization头中。
四、示例
下面以一个简单的python版本的应用服务器,来演示自定义header以及v2版本签名的使用。
运行附件的应用服务器示例代码,python2.7 callback_app_server.py,注意需要安装M2Crypto库。按照上例给出的x-oss-callback参数发起callback请求(将其中的callbackUrl改成你实际运行callback_app_server.py的地址和端口),即可回调成功。有任何问题,欢迎加入钉钉群(11799757)沟通交流。