Authorization 标头的签名计算:在多个分块中传输有效载荷(分块上传)(Amazon 签名版本 4)
如概述中所述,当使用 Authorization 标头对请求进行身份验证时,您可以选择分块上传有效载荷。您可以按固定大小或可变大小的分块发送数据。本节介绍分块上传中的签名计算过程、如何创建分块正文,以及延迟签名的工作原理,即您首先上传分块,然后在后续分块中发送其签名。示例部分(请参阅示例:PUT 对象)显示了签名计算和生成的 Authorization 标头,您可以将其用作测试套件来验证代码。
注意
在一系列分块中传输数据时,必须执行以下操作之一:
-
使用
Content-LengthHTTP 标头显式指定内容的总长度(以字节为单位的对象长度加上每个分块中的元数据)。为此,在开始请求之前,您必须预先计算有效载荷的总长度,包括您在每个分块中发送的元数据。 -
指定
Transfer-EncodingHTTP 标头。如果您包含Transfer-Encoding标头并指定除identity之外的任何值,则必须忽略Content-Length标头。
对于所有请求,您都必须包含 x-amz-decoded-content-length 标头,同时指定对象的大小(以字节为单位)。
每个分块签名计算都包括前一个分块的签名。首先,您仅使用标头来创建种子签名。在第一个分块的签名计算中使用种子签名。对于每个后续分块,您都要创建一个分块签名,其中包含前一个分块的签名。这样,分块签名链接在一起;也就是说,分块 n 的签名是函数 F(chunk n, signature(chunk n-1))。链接可确保您按正确的顺序发送分块。
要执行分块上传,请执行以下操作:
-
确定有效载荷分块大小。编写代码时需要此信息。
分块大小必须至少为 8 KB。为了获得更好的性能,我们建议分块大小至少为 64 KB。此分块大小适用于除最后一个分块之外的所有分块。您发送的最后一个分块可以小于 8 KB。如果有效载荷较小而适合放入一个分块中,则它可以小于 8 KB。
-
创建要包含在第一个分块中的种子签名。有关更多信息,请参阅 计算种子签名。
-
创建第一个分块并对其进行流式传输。有关更多信息,请参阅 定义分块正文。
-
对于每个后续分块,计算在您签名的字符串中包含先前签名的分块签名,构造该分块并发送它。有关更多信息,请参阅 定义分块正文。
-
发送最后一个额外的分块,它与构造中的其它分块相同,但其数据字节为零。有关更多信息,请参阅 定义分块正文。
计算种子签名
下图说明了计算种子签名的过程。
下表介绍了图中显示的函数。您需要为这些函数实现代码。
| 函数 | 说明 |
|---|---|
Lowercase() |
将字符串转换为小写。 |
Hex() |
base-16 编码的小写形式。 |
SHA256Hash() |
安全哈希算法(SHA)加密哈希函数。 |
HMAC-SHA256() |
使用 SHA256 算法和提供的签名密钥计算 HMAC。这是最终的签名。 |
Trim() |
删除所有前导空格或尾随空格。 |
UriEncode() |
URI 对每个字节进行编码。UriEncode() 必须强制执行以下规则:
重要由于底层 RFC 中的实现差异和相关歧义,您开发平台提供的标准 UrienCode 函数可能无法正常工作。建议您编写自己的自定义 UrienCode 函数,以确保编码能够正常工作。 以下是 Java 中的 UriEncode() 函数示例。
|
有关签名过程的信息,请参阅 Authorization 标头的签名计算:在单个分块中传输有效载荷(Amazon 签名版本 4)。过程是相同的,只是创建 CanonicalRequest 的过程有不同之处,如下所示:
-
除了您计划添加的请求标头外,还必须包括以下标头:
标题 说明 x-amz-content-sha256所有 Amazon 签名版本 4 请求都需要此标头。将值设置为
STREAMING-AWS4-HMAC-SHA256-PAYLOAD,以表示签名仅涵盖标头且没有有效载荷。Content-Encoding将值设置为
aws-chunked。Amazon S3 支持多个内容编码值。当使用签名版本 4 流式传输 API 时,您可以指定自定义内容编码。
例如:
Content-Encoding : aws-chunked,gzipAmazon S3 存储生成的对象,
content-encoding标头中不带aws-chunked值。如果aws-chunked是您在content-encoding标头中传递的唯一值,则 S3 会认为content-encoding标头为空,在您检索对象时不会返回此标头。x-amz-decoded-content-length将值设置为要分块的数据的长度(以字节为单位),而不计入任何元数据。例如,如果您要上传一个 4 GB 的文件,请将该值设置为 4294967296。这是要上传的对象的原始大小(您要存储在 Amazon S3 中的数据)。 Content-Length将该值设置为所传输的 HTTP 正文的实际大小,其中包括数据的长度(为
x-amz-decoded-content-length设置的值)以及分块元数据。每个分块都有元数据,例如前一个分块的签名。下一节将讨论分块计算。如果您包含Transfer-Encoding标头并指定除identity之外的任何值,则不得包含Content-Length标头。
您发送带有种子签名的第一个分块。您必须按下一节所述构造该分块。
定义分块正文
所有分块都包含一些元数据。每个分块都必须符合以下结构:
string(IntHexBase(chunk-size)) + ";chunk-signature=" +signature+ \r\n +chunk-data+ \r\n
其中:
-
IntHexBase()是您编写的用于将整数分块大小转换为十六进制的函数。例如,如果分块大小为 65536,则十六进制字符串为“10000”。 -
chunk-size是分块数据的大小(以字节为单位),不含元数据。例如,如果您要上传一个 65 KB 的对象,并且使用的分块大小为 64 KB,则将数据分成三个分块上传:第一个为 64 KB,第二个为 1 KB,最后一个分块为 0 字节。 -
signature对于每个分块,您可以使用以下待签字符串计算签名。对于第一个分块,使用种子签名作为前一个签名。
您发送的最后一个分块数据的大小为 0,尽管分块正文仍包含元数据(包括前一个分块的签名)。
示例:PUT 对象
您可以将本节中的示例用作参考,以检查代码中的签名计算。在查看示例之前,请注意以下事项:
-
这些示例中的签名计算使用以下示例安全凭证。
参数 值 AWSAccessKeyIdAKIAIOSFODNN7EXAMPLEAWSSecretAccessKeywJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY -
所有示例都使用请求时间戳 20130524T000000Z (
Fri, 24 May 2013 00:00:00 GMT)。 -
所有示例都使用
examplebucket作为存储桶名称。 -
假设存储桶位于美国东部(弗吉尼亚州北部)区域,凭证
Scope和Signing Key计算使用us-east-1作为区域说明符。有关更多信息,请参阅 Amazon Web Services 一般参考中的区域和终端节点。 -
您可以使用路径类型请求或虚拟托管类型请求。以下示例使用虚拟托管类型请求,例如:
https://examplebucket.s3.amazonaws.com/photos/photo1.jpg有关更多信息,请参阅《Amazon Simple Storage Service 用户指南》中的存储桶的虚拟托管。
以下示例发送 PUT 请求以上传对象。签名计算假设如下:
-
您正在上传一个 65 KB 的文本文件,文件内容是由字母“a”组成的单字符的字符串。
-
分块大小为 64 KB。因此,有效载荷分三个分块上传,分别为 64 KB、1 KB,以及包含 0 字节分块数据的最后一个分块。
-
生成的对象具有键名称
chunkObject.txt。 -
您正在通过添加
x-amz-storage-class请求标头来请求REDUCED_REDUNDANCY作为存储类别。
有关 API 操作的信息,请参阅 PutObject。常用请求语法如下:
PUT /examplebucket/chunkObject.txt HTTP/1.1 Host: s3.amazonaws.com x-amz-date: 20130524T000000Z x-amz-storage-class: REDUCED_REDUNDANCY Authorization:SignatureToBeCalculatedx-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD Content-Encoding: aws-chunked x-amz-decoded-content-length: 66560 Content-Length: 66824<Payload>
以下步骤显示了签名计算。
-
种子签名:创建待签字符串
-
CanonicalRequest
PUT /examplebucket/chunkObject.txt content-encoding:aws-chunked content-length:66824 host:s3.amazonaws.com x-amz-content-sha256:STREAMING-AWS4-HMAC-SHA256-PAYLOAD x-amz-date:20130524T000000Z x-amz-decoded-content-length:66560 x-amz-storage-class:REDUCED_REDUNDANCY content-encoding;content-length;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-storage-class STREAMING-AWS4-HMAC-SHA256-PAYLOAD在规范请求中,第三行是空的,因为请求中没有查询参数。最后一行是作为经过哈希处理的有效载荷值提供的常量字符串,应与
x-amz-content-sha256 header的值相同。 -
StringToSign
AWS4-HMAC-SHA256 20130524T000000Z 20130524/us-east-1/s3/aws4_request cee3fed04b70f867d036f722359b0b1f2f0e5dc0efadbc082b76c4c60e316455注意
有关待签字符串中每行的信息,请参阅解释种子签名计算的图表。
-
-
SigningKey
signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request") -
种子签名
4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9 -
Authorization 标头
生成的 Authorization 标头如下:
AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20130524/us-east-1/s3/aws4_request,SignedHeaders=content-encoding;content-length;host;x-amz-content-sha256;x-amz-date;x-amz-decoded-content-length;x-amz-storage-class,Signature=4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9 -
分块 1:(65536 字节,字母“a”的值为 97)
-
分块待签字符串:
AWS4-HMAC-SHA256-PAYLOAD 20130524T000000Z 20130524/us-east-1/s3/aws4_request 4f232c4386841ef735655705268965c44a0e4690baa4adea153f7db9fa80a0a9 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 bf718b6f653bebc184e1479f1935b8da974d701b893afcf49e701f3e2f9f9c5a注意
有关待签字符串中每行的信息,请参阅前面的图表,其中显示了待签字符串的各个组成部分(例如,最后三行是
previous-signature、hash("")和hash(current-chunk-data))。 -
分块签名:
ad80c730a21e5b8d04586a2213dd63b9a0e99e0e2307b0ade35a65485a288648 -
发送的分块数据:
10000;chunk-signature=ad80c730a21e5b8d04586a2213dd63b9a0e99e0e2307b0ade35a65485a288648 <65536-bytes>
-
-
分块 2:(1024 字节,字母“a”的值为 97)
-
分块待签字符串:
AWS4-HMAC-SHA256-PAYLOAD 20130524T000000Z 20130524/us-east-1/s3/aws4_request ad80c730a21e5b8d04586a2213dd63b9a0e99e0e2307b0ade35a65485a288648 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 2edc986847e209b4016e141a6dc8716d3207350f416969382d431539bf292e4a -
分块签名:
0055627c9e194cb4542bae2aa5492e3c1575bbb81b612b7d234b86a503ef5497 -
发送的分块数据:
400;chunk-signature=0055627c9e194cb4542bae2aa5492e3c1575bbb81b612b7d234b86a503ef5497 <1024 bytes>
-
-
分块 3:(0 字节数据)
-
分块待签字符串:
AWS4-HMAC-SHA256-PAYLOAD 20130524T000000Z 20130524/us-east-1/s3/aws4_request 0055627c9e194cb4542bae2aa5492e3c1575bbb81b612b7d234b86a503ef5497 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 -
分块签名:
b6c6ea8a5354eaf15b3cb7646744f4275b71ea724fed81ceb9323e279d449df9 -
发送的分块数据:
0;chunk-signature=b6c6ea8a5354eaf15b3cb7646744f4275b71ea724fed81ceb9323e279d449df9
-