我使用 Amazon S3 静态网站功能,但收到“访问被拒绝”错误。为什么会发生这种情况?

上次更新日期:2021 年 12 月 22 日

我使用 Amazon Simple Storage Service(Amazon S3)存储桶通过 S3 静态网站端点来托管静态网站。为什么我收到“访问被拒绝”错误?

简短描述

如果您尝试使用 Amazon S3 托管静态网站,但收到访问被拒绝错误,请检查是否满足以下要求:

  • 存储桶中的对象必须可公开访问。
  • S3 存储桶策略必须允许访问 s3:GetObject 操作。
  • 拥有存储桶的 AWS 账户必须同时拥有对象。
  • 对象无法使用 AWS Key Management Service(AWS KMS)加密。
  • 请求的对象必须存在于 S3 存储桶中。
  • 必须在存储桶和账户级别禁用“Amazon S3 阻止公开访问”。

解决方法

存储桶中的对象必须可公开访问

S3 静态网站端点仅支持可公开访问的内容。如要验证您的 S3 存储桶中的对象是否可公开访问,请在 Web 浏览器中打开对象的 URL。或者,您也可以对 URL 运行 cURL 命令。

下面是 S3 对象的示例 URL:

http://doc-example-bucket.s3-website-us-east-1.amazonaws.com/index.html
如果 Web 浏览器或 cURL 命令返回 访问被拒绝错误,则表示对象不可公开访问。要允许对您的 S3 对象进行公开读取访问,请创建 允许对存储桶中的所有对象进行公开读取访问的存储桶策略。

S3 存储桶策略必须允许访问 s3:GetObject 操作

检查您的存储桶策略,并确保没有任何阻止对 s3:GetObject 操作的公开读取访问的拒绝语句。即使您的存储桶策略中有 s3:GetObject 的显式允许语句,也请确认没有冲突的显式拒绝语句。显式拒绝语句将始终覆盖显式允许语句。

要查看 s3:GetObject 的存储桶策略,请执行以下步骤:

1.    打开 Amazon S3 控制台

2.    选择权限选项卡。

3.    选择存储桶策略

4.    查看存储桶策略,查找包含 "Action": "s3:GetObject" 或 "Action": "s3:*" 的语句。

5.    (可选)修改存储桶策略。 例如,您可以删除或编辑那些阻止公开读取访问 s3:GetObject 语句的语句。

拥有存储桶的 AWS 账户还必须拥有该对象

要允许公开读取访问对象,拥有该存储桶的 AWS 账户还必须拥有该对象。存储桶或对象归创建该存储桶或对象的 AWS Identity and Access Management(IAM)身份所属的账户所有。

注意:对象所有权要求适用于存储桶策略授予的公开读取访问权限。它不适用于对象的访问控制列表(ACL)授予的公开读取访问权限。

要验证您的 Amazon S3 存储桶和对象是否由同一 AWS 账户拥有,请执行以下步骤:

1.    要检索存储桶拥有者的 S3 规范 ID,请使用以下命令:

aws s3api list-buckets --query Owner.ID

2.    要检索对象拥有者的 S3 规范 ID,请使用以下命令:

aws s3api list-objects --bucket DOC-EXAMPLE-BUCKET --prefix index.html

注意:此示例显示单个对象。要检查多个对象,请使用 list 命令。

3.    确认存储桶拥有者和对象拥有者的规范 ID 是否匹配。如果不匹配,则表示该存储桶和对象的拥有者不同。

注意:您也可以使用 Amazon S3 控制台来检查存储桶和对象拥有者。拥有者可从相应存储桶或对象的权限选项卡中找到。

4.    如果存储桶和对象拥有者的规范 ID 不匹配,请将对象的拥有者更改为存储桶拥有者。

通过对象拥有者的账户,运行以下命令以检索分配给对象的 ACL 权限:

aws s3api get-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name

如果对象没有 bucket-owner-full-control ACL 权限,则通过对象拥有者的账户运行以下命令:

aws s3api put-object-acl --bucket DOC-EXAMPLE-BUCKET --key object-name --acl bucket-owner-full-control

如果对象具有 bucket-owner-full-control ACL 权限,则通过存储桶拥有者的账户运行以下命令。运行以下命令可通过将对象复制到其自身,来更改对象的所有者:

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html --storage-class STANDARD

您还可以使用 S3 对象所有权向存储桶拥有者授予由匿名用户或其他 AWS 账户上传的任何对象的自动所有权。

存储桶中的对象无法进行 AWS KMS 加密

AWS KMS 不支持匿名请求。 因此,任何允许匿名或公开访问的 Amazon S3 存储桶都不会应用于使用 AWS KMS 加密的对象。您必须从要使用 Amazon S3 静态网站端点提供的对象中删除 KMS 加密。

注意:使用 AES-256 加密您的对象,而不是使用 AWS KMS 加密。

您可以使用下述方法之一,来检查您存储桶中的对象是否为 KMS 加密对象:

  • 使用 Amazon S3 控制台来查看对象属性。查看加密对话框。如果已选中 AWS-KMS,则对象已进行 KMS 加密。
  • 您可以使用 AWS Command Line Interface(AWS CLI)运行 head-object 命令。如果命令返回的 ServerSideEncryption 为 aws:kms,则表明对象已进行 KMS 加密。

注意:如果在运行 AWS CLI 命令时收到错误,请确保您使用的是最新版本的 AWS CLI

要使用 Amazon S3 控制台更改对象的加密设置,请参阅指定 Amazon S3 加密

要使用 AWS CLI 更改对象的加密设置,您必须确认该对象的存储桶没有默认加密。如果存储桶没有默认加密,请通过将对象复制到其本身来删除对象的加密:

 

aws s3 cp s3://DOC-EXAMPLE-BUCKET/index.html s3://DOC-EXAMPLE-BUCKET/index.html --storage-class STANDARD
警告:将对象复制到其本身将会删除 storage-classwebsite-redirect-location 的设置。要在新对象中保留这些设置,请务必明确在复制请求中指定 storage-classwebsite-redirect-location 值。

请求的对象必须存在于 S3 存储桶中

如果执行请求的用户没有 s3:ListBucket 权限,则该用户会因对象缺失而收到访问被拒绝错误。

您可以运行 head-object AWS CLI 命令以检查存储桶中是否存在对象。

注意:S3 对象名称区分大小写。如果请求无有效的对象名称,则 Amazon S3 将报告该对象缺失。

如果存储桶中存在该对象,则访问被拒绝错误不会屏蔽 404 未找到错误。验证其他配置要求以解决访问被拒绝错误。

如果存储桶中不存在该对象,则访问被拒绝错误将屏蔽 404 未找到错误。解决与对象缺失相关的问题。

注意:启用公开 s3:ListBucket 访问权限不是安全最佳实践。启用公开 s3:ListBucket 访问权限会允许用户查看和列出存储桶中的所有对象。此访问将向用户公开对象元数据详细信息(例如,密钥和大小),即使用户没有下载相应对象的权限。

必须在存储桶上禁用“Amazon S3 阻止公开访问”。

“Amazon S3 阻止公开访问”设置可以应用于各个存储桶或 AWS 账户。确认您的 S3 存储桶AWS 账户没有应用任何 Amazon S3 阻止公开访问设置。这些设置会覆盖允许公开读取访问的权限。


这篇文章对您有帮助吗?


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