我使用 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 命令行界面(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-class 和
website-redirect-location 的设置。要在新对象中保留这些设置,请务必明确在复制请求中指定
storage-class 或
website-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 阻止公开访问设置。这些设置会覆盖允许公开读取访问的权限。