如何故障排除与 CloudFront 中的已签名 URL 或已签名 Cookie 相关的问题?

上次更新日期:2022 年 6 月 2 日

我正在使用 Amazon CloudFront 和已签名 URL 或已签名 Cookie 来保护私有内容。我收到 403 Access Denied(403 访问被拒绝)错误。如何对此错误进行故障排除?

简短描述

如果已签名 URL 或已签名 Cookie 存在问题,则 Amazon CloudFront 可能会返回 403 Access Denied(403 访问被拒绝)错误。有关此错误的原因和故障排除步骤,请参阅以下解决方法部分。

解决方法

在行为中启用 Restrict Viewer Access(限制查看器访问)时,您必须确定签署人。签署人可以是您在 CloudFront 中创建的可信密钥组,也可以是包含 CloudFront 密钥对的 AWS 账户。以下 403 错误消息表示签署人信息缺失或不正确:

403 Access Denied(403 访问被拒绝)错误,并显示消息 "Missing Key-Pair-Id query parameter or cookie value"(缺少 Key-Pair-Id 查询参数或 Cookie 值)。

此消息表示在已签名 URL 中缺少查询字符串参数 Key-Pair-ID 或为空。

403 Access Denied(403 访问被拒绝)错误,并显示消息 "Missing Key-Pair-Id query parameter or cookie value"(缺少 Key-Pair-Id 查询参数或 Cookie 值)。

此消息表示已签名 Cookie 中缺少查询字符串参数 CloudFront-Key-Pair-ID 或为空。

403 Access Denied(403 访问被拒绝)错误,并显示消息 "Unknown Key"(未知密钥)。

此消息表示 CloudFront 无法通过 Key-Pair-ID(对于已签名 URL)或 CloudFront-Key-Pair-ID(对于已签名 Cookie)验证签署人信息。要解决此问题,请确认用于已签名 URL 的 Key-Pair-ID 或用于已签名 Cookie 的 CloudFront-Key-Pair-ID 是否正确。首先:

如果您使用的是已签名 URL,请查找并记下 Key-Pair-ID 的值。
-或者-
如果您使用的是已签名 Cookie,请查找并记下 CloudFront-Key-Pair-ID 的值。

然后,找到 Key ID 并确认它与 Key-Pair-IDCloudFront-Key-Pair-ID 是否匹配:

  1. 打开 CloudFront 控制台。在左侧导航菜单中,选择 Distributions(分发)。
  2. 选择您的分发。然后,选择 Behaviors(行为)选项卡。
  3. 选择行为名称,然后选择 Edit(编辑)。
  4. 找到 Restrict viewer access(限制查看器访问)设置。
    注意:如果将其设置为 Yes(是),则对与此缓存行为的路径模式匹配的文件的请求必须使用已签名 URL 或已签名 Cookie。
  5. 确认 Restrict view access(限制查看访问)字段设置为 Yes(是)后,选中 Trusted authorization type(可信授权类型)字段。
  6. 如果 Trusted authorization type(可信授权类型)设置的值为 Trusted key groups(可信密钥组),请记下信任密钥组的名称。
    然后,找到信任密钥组的公钥 ID:返回 CloudFront 控制台。选择 Key Groups(密钥组)。在密钥组列表中,选择您记下的可信密钥组的名称。
    确认您在步骤 1 中记下的 Key-Pair-IdCloudFront-Key-Pair-Id 的值与可信密钥组中的一个公钥 ID 匹配。
  7. 如果 Trusted authorization(可信授权)类型的值为 Trusted Signer(可信签署人),则使用 AWS 生成的 CloudFront 凭证。在这种情况下,您在步骤 1 中记下的 Key-Pair-IdCloudFront-Key-Pair-Id 的值必须与 CloudFront 凭证的访问密钥 ID 相匹配。
    要查找 CloudFront 凭证的访问密钥 ID,请参阅为签署人创建密钥对

当您创建已签名 URL 或已签名 Cookie 时,JSON 格式的策略语句会指定对已签名 URL 的限制。此语句确定 URL 的有效期限。在以下情况下,CloudFront 将返回 403 Access Denied(403 访问被拒绝)错误:

  • 已签名 URL 的发送时间大于使用标准策略的已签名 URL 中的 Expires 值。
  • 已签名 Cookie 的发送时间大于使用标准策略的已签名 Cookie 中的 CloudFront-Expires 值。
  • 在自定义策略中,已签名 URL 或已签名 Cookie 的发送时间大于 DateLessThan 值或小于 DateGreaterThan 值。

注意ExpiresCloudFront-ExpiresDateLessThanDateGreaterThan 的值采用 Unix 时间格式(以秒为单位)和协调世界时(UTC)。例如,2013 年 1 月 1 日上午 10:00 UTC 将转换为 Unix 时间格式的 1357034400。如果使用纪元时间,则请对不迟于 2147483647(协调世界时 2038 年 1 月 19 日 03:14:07)的日期使用 32 位整数。

已签名 URL 中的 Policy 参数或已签名 Cookie 中的 CloudFront-Policy 属性表示使用了自定义策略。该策略语句采用 JSON 格式并采用 base64 编码。要找出 DateLessThanDateGreaterThan 的值,请使用 64base 解码命令。

base64 编码自定义策略的示例如下所示:

eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QxMTExMTFhYmNkZWY4LmNsb3VkZnJvbnQubmV0L2dhbWVfZG93bmxvYWQuemlwIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIxOTIuMC4yLjAvMjQifSwiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE0MjY1MDAwMDB9fX1dfQ__

使用以下 Linux 命令将 base64 编码格式的自定义策略解码为 JSON 格式。此示例使用前一个示例中的值。替换为您自己的自定义策略。

$ echo -n eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cDovL2QxMTExMTFhYmNkZWY4LmNsb3VkZnJvbnQubmV0L2dhbWVfZG93bmxvYWQuemlwIiwiQ29uZGl0aW9uIjp7IklwQWRkcmVzcyI6eyJBV1M6U291cmNlSXAiOiIxOTIuMC4yLjAvMjQifSwiRGF0ZUxlc3NUaGFuIjp7IkFXUzpFcG9jaFRpbWUiOjE0MjY1MDAwMDB9fX1dfQ__ | base64 -di

命令的输出应与以下类似:

{ "Statement": [{ "Resource": "http://d111111abcdef8.cloudfront.net/game_download.zip", "Condition": { "IpAddress": { "AWS:SourceIp": "192.0.2.0/24" }, "DateLessThan": { "AWS:EpochTime": 1426500000 } } }] }

如果标准策略或自定义策略中包含多条语句,则 CloudFront 将返回 403 Access Denied(403 访问被拒绝)错误。

要进行故障排除,请使用上一节中的 Linux 命令检查自定义策略的语句。验证您的代码详细信息,并确认标准策略或自定义策略中仅包含一条语句。

如果出现以下情况,CloudFront 将返回 403 Access Denied(403 访问被拒绝)错误:

  • 策略语句关键 Resource(资源)中的基本 URL 有一个缩写 URL(www.example.com)。使用完整的 URL(http://www.example.com)。
  • 基本 URL 没有 UTF-8 字符编码。
  • 基本 URL 不包含所有标点符号和参数名称。
  • 基本 URL 中的 HTTP 或 HTTPS 协议与发送已签名 URL 或已签名 Cookie 的请求中使用的协议不匹配。
  • 基本 URL 中的域名与发送已签名 URL 或已签名 Cookie 的用户代理所使用的主机标头值不匹配。
  • 基本 URL 查询字符串包含无效字符。

如果出现以下情况,CloudFront 将返回 403 Access Denied(403 访问被拒绝)错误:

  • 策略语句包含空格(包括制表符和换行符)。
  • 标准策略或自定义策略在哈希处理之前没有格式化为字符串。如果您在不使用 AWS SDK 的情况下创建已签名 URL 或已签名 Cookie,则可能会发生这种情况。
  • 在生成签名之前,该策略未经过哈希处理。如果您正在不使用 AWS SDK 的情况下创建已签名 URL 或已签名 Cookie,则可能会发生这种情况。

有关使用已签名 URL 或已签名 Cookie 时的签名最佳实践,请参阅为已签名 URL 创建签名的代码示例

如果出现以下情况,CloudFront 将返回 403 Access Denied(403 访问被拒绝)错误:

  • 已签名 URL 或已签名 Cookie 是从 IPv6 IP 地址发送的。
  • 已签名 URL 或已签名 Cookie 不是从自定义策略中指定的 IPv4 地址或 IPv4 IP 范围发送的。

密钥 IpAddress 仅在已签名 URL 或已签名 Cookie 的自定义策略中可用。不支持 IPv6 格式的 IP 地址。如果您使用包含 IpAddress 的自定义策略,则请勿为分发启用 IPv6。

如果从 CloudFront 返回 Cookie 但未包含在对同一域的后续请求中,则 CloudFront 将返回 403 Access Denied(403 访问被拒绝)错误。在这种情况下,请检查 Set-Cookie 响应标头中的 Cookie 属性 DomainPath

Domain 值是所请求文件的域名。如果未指定 Domain 属性,则默认值为 URL 中的域名。这仅适用于指定的域名,不适用于子域。如果您指定了 Domain 属性,则它也适用于子域。

如果您指定了 Domain 属性,则 URL 中的域名和 Domain 属性的值必须匹配。您可以指定 CloudFront 分配给您的分发的域名(例如 d111111abcdef8.cloudfront.net),但不能为域名指定 *.cloudfront.net。要在 URL 中使用备用域名(例如 example.com),请将备用域名添加到分发中。

Path 值是所请求文件的路径。如果未指定 Path 属性,则默认值为 URL 中的路径。


这篇文章对您有帮助吗?


您是否需要账单或技术支持?