View a markdown version of this page

对请求进行身份验证:使用查询参数(Amazon 签名版本 4) - Amazon Simple Storage Service
Amazon Web Services 文档中描述的 Amazon Web Services 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅 中国的 Amazon Web Services 服务入门 (PDF)

对请求进行身份验证:使用查询参数(Amazon 签名版本 4)

如身份验证概述(请参阅身份验证方法)中所述,您可以使用查询字符串参数提供身份验证信息。当您想要在 URL 中完整表达请求时,使用查询参数对请求进行身份验证很有用。此方法也称为对 URL 进行预签名。

预签名 URL 的一个使用案例场景是,您可以授予对 Amazon S3 资源的临时访问权限。例如,您可以在网站上嵌入预签名 URL,或者在命令行客户端(例如 Curl)中使用它来下载对象。

注意

也可以使用 Amazon CLI 来创建预签名 URL。有关更多信息,请参阅《Amazon CLI Command Reference》中的 presign

以下是示例预签名 URL。

https://examplebucket.s3.amazonaws.com/test.txt ?X-Amz-Algorithm=AWS4-HMAC-SHA256 &X-Amz-Credential=<your-access-key-id>/20130721/us-east-1/s3/aws4_request &X-Amz-Date=20130721T201207Z &X-Amz-Expires=86400 &X-Amz-SignedHeaders=host &X-Amz-Signature=<signature-value>

在示例 URL 中,注意以下各项:

  • 为了便于阅读,添加了换行符。

  • URL 中的 X-Amz-Credential 值显示“/”字符只是为了方便阅读。实际上,它应该编码为 %2F。例如:

    &X-Amz-Credential=<your-access-key-id>%2F20130721%2Fus-east-1%2Fs3%2Faws4_request

下表介绍了 URL 中提供身份验证信息的查询参数。

查询字符串参数名称 示例值
X-Amz-Algorithm

标识 Amazon 签名版本以及用于计算签名的算法。

对于 Amazon 签名版本 4,您可以将此参数值设置为 AWS4-HMAC-SHA256。该字符串标识 Amazon 签名版本 4(Amazon4)和 HMAC-SHA256 算法(HMAC-SHA256)。

X-Amz-Credential

除了访问密钥 ID 外,该参数还提供签名有效的范围(Amazon Web Services 区域和服务)。该值必须与您在签名计算中使用的范围匹配(后续部分将对此进行说明)。该参数值的一般形式如下:

<your-access-key-id>/<date>/<Amazon Web Services 区域>/<Amazon-service>/aws4_request

例如:

AKIAIOSFODNN7EXAMPLE/20130721/us-east-1/s3/aws4_request

对于 Amazon S3,Amazon-service 字符串为 s3。有关 S3 AWS-region 字符串的列表,请参阅《Amazon Web Services 一般参考》中的区域和端点

X-Amz-Date

日期和时间格式必须遵循 ISO 8601 标准,并且必须按照“yyyyMMddTHHmmssZ”格式进行格式化。例如,如果日期和时间是“08/01/2016 15:32:41.982-700”,则必须先将其转换为 UTC(协调世界时),然后以“20160801T223241Z”形式提交。

X-Amz-Expires

提供生成的预签名 URL 的有效时间段(以秒为单位)。例如,86400(24 小时)。该值是一个整数。您可以设置的最小值为 1,最大值为 604800(七天)。

预签名 URL 的有效期最长为七天,因为您在签名计算中使用的签名密钥的有效期最长为七天。

X-Amz-SignedHeaders

列出用于计算签名的标头。签名计算中需要以下标头:

  • HTTP host 标头。

  • 您计划添加到请求的任何 x-amz-* 标头。

注意

为了提高安全性,您应该签署计划在请求中包含的所有请求标头。

X-Amz-Signature

提供签名以验证您的请求。该签名必须与 Amazon S3 计算出的签名相匹配;否则 Amazon S3 会拒绝该请求。例如, 733255ef022bec3f2a8701cd61d4b371f3f28c9f193a1f02279211d48d5193d7

以下部分将介绍签名计算:

X-Amz-Security-Token

如果使用来自 STS 服务的凭证,则为可选凭证参数。

计算签名

下图说明了签名计算过程。

Amazon 签名版本 4 签名流程,包括规范请求、待签字符串和签名生成步骤。

下表介绍了图中显示的函数。您需要为这些函数实现代码。

函数 说明
Lowercase() 将字符串转换为小写。
Hex() base-16 编码的小写形式。
SHA256Hash() 安全哈希算法(SHA)加密哈希函数。
HMAC-SHA256() 使用 SHA256 算法和提供的签名密钥计算 HMAC。这是最终的签名。
Trim() 删除所有前导空格或尾随空格。
UriEncode()

URI 对每个字节进行编码。UriEncode() 必须强制执行以下规则:

  • URI 对除非预留字符之外的所有字节进行编码:“A”-“Z”、“a”-“z”、“0”-“9”、“-”、“.”、“_”和“~”。

  • 空格字符是预留字符,必须编码为“%20”(而不是“+”)。

  • 每个 URI 编码字节由“%”和该字节的两位十六进制值组成。

  • 十六进制值中的字母必须为大写,例如“%1A”。

  • 对除对象键名称之外的所有位置的正斜杠字符“/”进行编码。例如,如果对象键名称是 photos/Jan/sample.jpg,则不会对键名称中的正斜杠进行编码。

重要

由于底层 RFC 中的实现差异和相关歧义,您开发平台提供的标准 UrienCode 函数可能无法正常工作。建议您编写自己的自定义 UrienCode 函数,以确保编码能够正常工作。

以下是 Java 中的 UriEncode() 函数示例。

public static String UriEncode(CharSequence input, boolean encodeSlash) { StringBuilder result = new StringBuilder(); for (int i = 0; i < input.length(); i++) { char ch = input.charAt(i); if ((ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '-' || ch == '~' || ch == '.') { result.append(ch); } else if (ch == '/') { result.append(encodeSlash ? "%2F" : ch); } else { result.append(toHexUTF8(ch)); } } return result.toString(); }

有关签名过程(创建规范请求、待签字符串和签名计算的详细信息)的更多信息,请参阅 Authorization 标头的签名计算:在单个分块中传输有效载荷(Amazon 签名版本 4)。除了在预签名 URL 中创建 CanonicalRequest 之外,过程大致相同,如下所示:

  • 您未在规范请求中包含有效载荷哈希值,原因是当您创建预签名 URL 时,您并不知道有效载荷内容,因为该 URL 用于上传任意有效载荷。而应使用常量字符串 UNSIGNED-PAYLOAD

  • 规范查询字符串必须包含上表中除 X-Amz-Signature 之外的所有查询参数。

  • 对于 S3,如果使用源自 STS 服务的凭证,您必须在 URL 中包含 X-Amz-Security-Token 查询参数。

  • 规范标头必须包含 HTTP host 标头。如果您计划包含任何 x-amz-* 标头,则还必须添加这些标头以进行签名计算。您可以选择添加您计划在请求中包含的所有其它标头。为了提高安全性,您应该对尽可能多的标头进行签名。如果您添加的已签名标头也是已签名的查询参数,而它们的值不同,则由于输入存在冲突,您将收到 InvalidRequest 错误消息。

一个示例

假设您的 examplebucket 存储桶中有一个对象 test.txt。您希望通过创建预签名 URL 与他人共享此对象达 24 小时(86400 秒)。

https://examplebucket.s3.amazonaws.com/test.txt ?X-Amz-Algorithm=AWS4-HMAC-SHA256 &X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request &X-Amz-Date=20130524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host &X-Amz-Signature=<signature-value>

以下步骤首先说明签名计算,然后说明预签名 URL 的构造。该示例作出以下附加假设:

  • 请求时间戳为 Fri, 24 May 2013 00:00:00 GMT

  • 存储桶位于美国东部(弗吉尼亚州北部)区域,凭证 ScopeSigning Key 计算使用 us-east-1 作为区域说明符。有关更多信息,请参阅 https://docs.amazonaws.cn/general/latest/gr/rande.html#s3_region 中的Amazon Web Services 一般参考区域和终端节点

您可以将此示例用作测试用例来验证您的代码计算的签名;但是,您必须使用相同的存储桶名称、对象键、时间戳和以下示例凭证:

参数
AWSAccessKeyId AKIAIOSFODNN7EXAMPLE
AWSSecretAccessKey wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
  1. StringToSign
    1. CanonicalRequest

      GET /test.txt X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20130524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host host:examplebucket.s3.amazonaws.com host UNSIGNED-PAYLOAD

    2. StringToSign

      AWS4-HMAC-SHA256 20130524T000000Z 20130524/us-east-1/s3/aws4_request 3bfa292879f6447bbcda7001decf97f4a54dc650c8942174ae0a9121cf58ad04

  2. SigningKey

    signing key = HMAC-SHA256(HMAC-SHA256(HMAC-SHA256(HMAC-SHA256("AWS4" + "<YourSecretAccessKey>","20130524"),"us-east-1"),"s3"),"aws4_request")

  3. Signature

    aeeed9bbccd4d02ee5c0109b86d86835f995330da4c265957d157751f604d404

    现在,您已经掌握了构造预签名 URL 的所有信息。此示例生成的 URL 如下所示(您可以使用它来比较您的预签名 URL):

    https://examplebucket.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20130524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host&X-Amz-Signature=aeeed9bbccd4d02ee5c0109b86d86835f995330da4c265957d157751f604d404

示例 2

以下是一个显示带有 X-Amz-Security-Token 参数的预签名 URL 的示例(与前一个示例无关)。

https://examplebucket.s3.us-east-1.amazonaws.com/test.txt ?X-Amz-Algorithm=AWS4-HMAC-SHA256 &X-Amz-Credential=AKIAIOSFODNN7EXAMPLE%2F20130524%2Fus-east-1%2Fs3%2Faws4_request &X-Amz-Date=20200524T000000Z&X-Amz-Expires=86400&X-Amz-SignedHeaders=host &X-Amz-Security-Token=IQoJb3JpZ2luX2VjEMv%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCXVzLWVhc3QtMSJGMEQCIBSUbVdj9YGs2g0HkHsOHFdkwOozjARSKHL987NhhOC8AiBPepRU1obMvIbGU0T%2BWphFPgK%2Fqpxaf5Snvm5M57XFkCqlAgjz%2F%2F%2F%2F%2F%2F%2F%2F%2F%2F8BEAAaDDQ3MjM4NTU0NDY2MCIM83pULBe5%2F%2BNm1GZBKvkBVslSaJVgwSef7SsoZCJlfJ56weYl3QCwEGr2F4BmCZZyFpmWEYzWnhNK1AnHMj5nkfKlKBx30XAT5PZGVrmq4Vkn9ewlXQy1Iu3QJRi9Tdod8Ef9%2FyajTaUGh76%2BF5u5a4O115jwultOQiKomVwO318CO4l8lv%2F3HhMOkpdanMXn%2B4PY8lvM8RgnzSu90jOUpGXEOAo%2F6G8OqlMim3%2BZmaQmasn4VYRvESEd7O72QGZ3%2BvDnDVnss0lSYjlv8PP7IujnvhZRnj0WoeOyMe1lL0wTG%2Fa9usH5hE52w%2FYUJccOn0OaZuyROuVsRV4Q70sbWQhUvYUt%2B0tUMKzm8vsFOp4BaNZFqobbjtb36Y92v%2Bx5kY6i0s8QE886jJtUWMP5ldMziClGx3p0mN5dzsYlM3GyiJ%2FO1mWkPQDwg3mtSpOA9oeeuAMPTA7qMqy9RNuTKBDSx9EW27wvPzBum3SJhEfxv48euadKgrIX3Z79ruQFSQOc9LUrDjR%2B4SoWAJqK%2BGX8Q3vPSjsLxhqhEMWd6U4TXcM7ku3gxMbzqfT8NDg%3D &X-Amz-Signature=<signature-value>