创建已签名的 AWS API 请求
下文概述了创建已签名的请求的流程。如需了解更多信息,请参阅 AWS 软件开发工具包中的代码示例。
第 1 步:创建规范请求
串联以下由换行符分隔的字符串,以创建规范请求。这有助于确保您计算出的签名与 AWS 计算出的签名相匹配。
HTTPMethod
CanonicalUri
CanonicalQueryString
CanonicalHeaders
SignedHeaders
HashedPayload
-
HTTPMethod
– HTTP 方法。 -
CanonicalUri
– 绝对路径组件 URL 的 URI 编码版本(主机和以问号字符(?)开头的查询字符串参数之间的所有内容)。如果绝对路径为空,则使用正斜杠字符(/)。 -
CanonicalQueryString
– 用连字符(&)分隔的 URL 编码的查询字符串参数。对预留字符(包括空格字符)进行百分号编码。分别对名称和值进行编码。如果参数为空,请在编码之前在参数名称后面加上等号。编码后,按键名称的字母顺序对参数进行排序。如果没有查询字符串,请使用空字符串 ("")。 -
CanonicalHeaders
– 将签署的请求标头及其值,由换行符分隔。标头名称必须使用小写字符,必须按字母顺序显示,必须在后面加上冒号(:)。对于这些值,去除所有前导空格或尾部空格,将连续空格转换为单个空格,并使用逗号分隔多值标头的值。您必须在签名中包含host
标头(HTTP/1.1)或:authority
标头(HTTP/2)以及任何x-amz-*
标头。您可选择在签名中包含其他标准标头,例如content-type
。 -
SignedHeaders
– 包含在CanonicalHeaders
中的标头列表,由分号(;)分隔。这表明哪些标头是签名过程的一部分。标头名称必须使用小写字符,必须按字母顺序显示。 -
HashedPayload
– 使用 HTTP 请求正文中的负载作为哈希函数的输入创建的字符串。此字符串使用小写十六进制字符。如果有效负载为空,则使用空字符串作为哈希函数的输入。
以下是调用 Amazon EC2 DescribeInstances
API 操作的规范请求的示例。
GET
/
Action=DescribeInstances&Version=2016-11-15
content-type:application/x-www-form-urlencoded; charset=utf-8
host:ec2.amazonaws.com
x-amz-date:20220830T123600Z
host;x-amz-date
payload-hash
第 2 步:创建规范请求的哈希
使用创建负载的哈希时所使用的相同算法来创建规范请求的哈希(摘要)。经过哈希处理的规范请求必须以小写十六进制字符串形式表示。
第 3 步:创建要签名的字符串
串联以下由换行符分隔的字符串,以创建字符串。请勿使用换行符作为此字符串的结尾。
Algorithm
RequestDateTime
CredentialScope
HashedCanonicalRequest
-
Algorithm
– 用于创建规范请求的哈希的算法。对于 SHA-256,算法是AWS4-HMAC-SHA256
。 -
RequestDateTime
– 在凭证范围内使用的日期和时间。 -
CredentialScope
– 凭证范围。这会将生成的签名限制在指定的区域和服务范围内。该字符串采用以下格式:YYYYMMDD
/region
/service
/aws4_request。 -
HashedCanonicalRequest
– 规范请求的哈希。
以下是要签名的字符串的示例。
AWS4-HMAC-SHA256
20220830T123600Z
20220830/us-east-1/ec2/aws4_request
canonical-request-hash
第 4 步:计算签名
创建要签名的字符串后,即可计算要添加至请求的身份验证信息的签名。对于每个步骤,使用所需的密匙和数据调用哈希函数。
hash(key, data)
每次调用哈希函数的结果都会变成下一次调用哈希函数的输入。
必填项
字符串
Key
,其中包含您的秘密访问密钥字符串
Date
,其中包含在凭证范围中使用的日期,格式为 YYYYMMDD字符串
Region
,其中包含区域代码(例如,us-east-1
)字符串
Service
,其中包含服务代码(例如,ec2
)在上一步中创建的要签名的字符串。
计算签名
-
连接“AWS4”和秘密访问密钥。使用密钥和数据调用哈希函数,并将连接的字符串作为密钥,而日期字符串作为数据。
kDate = hash("AWS4" + Key, Date)
-
使用密钥和数据调用哈希函数,并将上一次调用的结果作为密钥,而区域字符串作为数据。
kRegion = hash(kDate, Region)
-
使用密钥和数据调用哈希函数,并将上一次调用的结果作为密钥,而服务字符串作为数据。
kService = hash(kRegion, Service)
-
使用密钥和数据调用哈希函数,并将上一次调用的结果作为密钥,而“aws4_request”作为数据。
kSigning = hash(kService, "aws4_request")
-
使用密钥和数据调用哈希函数,并将上一次调用的结果作为密钥,而要签名的字符串作为数据。结果是作为二进制值的签名。
signature = hash(kSigning,
string-to-sign
) -
将签名从二进制转换为十六进制表示形式,使用小写字符。
第 5 步:将签名添加至请求。
您可使用 HTTP Authorization
标头或查询字符串参数,将身份验证信息添加至请求。您无法同时使用 Authorization
标头和查询字符串参数来添加身份验证信息。
例 示例:授权标头
以下示例显示了 DescribeInstances
操作的 Authorization
标头。为便于阅读,此示例已使用换行符编排过格式。在您的代码中,这必须是连续的字符串。算法和 Credential
之间没有逗号。但是,必须使用逗号分隔其他元素。
Authorization: AWS4-HMAC-SHA256
Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request,
SignedHeaders=host;x-amz-date,
Signature=calculated-signature
例 示例:请求在查询字符串中使用身份验证参数
以下示例显示了对包含身份验证信息的 DescribeInstances
操作的查询。为便于阅读,此示例已使用换行符编排过格式,而非 URL 编码。在您的代码中,查询字符串必须是采用 URL 编码的连续字符串。
https://ec2.amazonaws.com/?
Action=DescribeInstances&
Version=2016-11-15&
X-Amz-Algorithm=AWS4-HMAC-SHA256&
X-Amz-Credential=AKIAIOSFODNN7EXAMPLE/20220830/us-east-1/ec2/aws4_request&
X-Amz-Date=20220830T123600Z&
X-Amz-SignedHeaders=host;x-amz-date&
X-Amz-Signature=calculated-signature
临时安全凭证
您可使用 AWS Security Token Service(AWS STS)提供的临时安全凭证来签署请求,而不是使用长期凭证。
使用临时安全凭证时,必须将 X-Amz-Security-Token
添加至授权标头或查询字符串以保存会话令牌。某些服务会要求您将 X-Amz-Security-Token
添加至规范请求。其他服务仅会要求您在计算出签名后在末尾添加 X-Amz-Security-Token
。有关详细信息,请查看每种 AWS 服务 的文档。
AWS 软件开发工具包中的代码示例
AWS 软件开发工具包包括 GitHub 上的源代码,显示了如何签署 AWS API 请求。
-
AWS SDK for .NET – AWS4Signer.cs
-
AWS SDK for C++ – AWSAuthV4Signer.cpp
-
AWS SDK for Go – v4.go
-
AWS SDK for Java – BaseAws4Signer.java
-
AWS SDK for JavaScript – v4.js
-
AWS SDK for PHP – SignatureV4.php
-
AWS SDK for Python (Boto) – signers.py
-
AWS SDK for Ruby – signer.rb