CloudFront访问S3返回403?OAC权限排查指南
本内容发表于:2026-07-31 10:36:01
浏览量
1014

CloudFront 使用 Amazon S3 作为源站时返回 403,不一定只是“存储桶没有公开”。常见原因包括 OAC 没有绑定到正确的源、存储桶策略中的分配 ARN 写错、源站类型选择错误、对象名称或路径不存在、默认根对象配置不正确、SSE-KMS 权限缺失,以及旧的 403 响应仍保留在 CloudFront 缓存中。

正确的处理方式不是立即关闭 S3 Block Public Access,而是先判断 403 发生在哪一层,再检查 CloudFront 到 S3 的私有访问链路。对于私有 S3 源,推荐保持存储桶不公开,并使用 Origin Access Control(OAC)授权指定的 CloudFront 分配读取对象。

本文配置核查日期为 2026 年 7 月 31 日。命令和策略中的账号、存储桶、分配 ID、域名及对象路径均为占位符,使用时必须替换为自己的值。

先判断:是哪一种 403?

先用下面的现象缩小范围,比反复修改权限更有效。

  1. 所有文件都返回 403:优先检查源站类型、OAC 绑定、S3 存储桶策略、显式 Deny 和 KMS 密钥策略。

  2. 只有根域名返回 403,但 /index.html 正常:优先检查 CloudFront 默认根对象。

  3. 只有某个文件返回 403:检查对象是否存在、大小写、前缀路径、对象所有权和加密方式。

  4. 权限修复后仍返回旧 403:检查错误缓存 TTL,并对对应对象执行缓存失效。

  5. 只有部分用户返回 403:检查地理限制、AWS WAF、签名 URL、签名 Cookie 和查看器访问限制。

可先分别请求根路径和一个确定存在的对象:

curl -I https://cdn.example.com/
curl -I https://cdn.example.com/index.html
curl -I https://cdn.example.com/assets/app.css

重点记录状态码、serverx-cacheviax-amz-cf-id。如果根路径失败而具体对象成功,通常不应先改存储桶权限。

第一步:确认使用的是普通 S3 源还是网站端点

这是最容易混淆的配置之一。CloudFront 中常见的 S3 源有两种:

  • 普通 S3 存储桶 REST 端点:可以使用 OAC,适合私有存储桶,也是本文重点讨论的方式。

  • S3 静态网站端点:必须在 CloudFront 中作为自定义源使用,不能使用 OAC 或 OAI;网站端点本身还要求内容可公开读取。

如果目标是“用户只能通过 CloudFront 访问文件,不能直接访问 S3”,应选择普通 S3 存储桶源并配置 OAC,而不是选择 S3 网站端点。

不要为了修复 403 直接关闭 Block Public Access。 如果原本设计的是私有 S3 源,公开存储桶可能掩盖 OAC 配置错误,并扩大数据暴露范围。

第二步:检查 OAC 是否绑定到正确的 CloudFront 源

创建 OAC 并不等于已经启用。还需要把它绑定到当前分配实际使用的 S3 源。

  1. 进入 CloudFront 控制台并选择对应分配。

  2. 打开“源”页面,选择实际的 S3 源并编辑。

  3. 在源访问设置中选择 Origin Access Control。

  4. 确认选择的是正确的 OAC,而不是仅创建但未绑定的 OAC。

  5. 签名行为优先使用“始终签署请求(推荐)”。

  6. 保存后等待分配状态完成部署,再重新测试。

使用推荐的“始终签名”设置时,CloudFront 会使用 SigV4 为发送到 S3 的源请求签名。若选择“不签名”,私有存储桶将无法通过该 OAC 正常访问。

第三步:检查 S3 存储桶策略

OAC 模式下,存储桶策略通常需要允许 CloudFront 服务主体执行 s3:GetObject,同时使用 AWS:SourceArn 将权限限制到指定分配。

只读静态内容可以从下面的最小策略开始:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowCloudFrontReadOnly",
      "Effect": "Allow",
      "Principal": {
        "Service": "cloudfront.amazonaws.com"
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::YOUR_BUCKET_NAME/*",
      "Condition": {
        "StringEquals": {
          "AWS:SourceArn": "arn:aws:cloudfront::YOUR_ACCOUNT_ID:distribution/YOUR_DISTRIBUTION_ID"
        }
      }
    }
  ]
}

检查时重点关注以下位置:

  • Resource 是否包含 /*:读取对象需要匹配对象 ARN,而不只是存储桶 ARN。

  • 账号 ID 和分配 ID 是否正确:不要把 OAC ID、源 ID 或分配域名误填到 SourceArn。

  • Principal 是否正确:OAC 使用 CloudFront 服务主体,不是旧版 OAI 的 IAM ARN。

  • 是否存在显式 Deny:组织 SCP、权限边界、VPC 端点策略、存储桶策略中的 Deny 都可能覆盖 Allow。

  • 是否限制了前缀:如果 Resource 只允许 public/*,请求其他目录仍会被拒绝。

如果正在从 OAI 迁移到 OAC,可以在部署过渡期同时保留 OAI 和 OAC 的读取授权;确认新配置已在所有边缘节点部署后,再删除旧 OAI 权限。这样可以减少切换过程中出现 403 的概率。

第四步:确认对象存在,路径与大小写完全一致

S3 对象键区分大小写。index.htmlIndex.htmlINDEX.HTML 是三个不同的对象。URL 中多一个目录、少一个前缀或大小写不同,都可能表现为 AccessDenied。

可使用 AWS CLI 检查对象是否存在:

aws s3api head-object \
  --bucket YOUR_BUCKET_NAME \
  --key index.html

如果使用了 CloudFront 的 Origin Path,还要把它计算进最终对象键。例如源路径配置为 /production,查看器请求 /index.html 时,CloudFront 实际可能访问 S3 中的 production/index.html

还应检查 S3 Object Ownership。AWS 对新的存储桶默认使用 Bucket owner enforced,并禁用 ACL。OAC 场景通常应使用此设置并通过存储桶策略管理访问;如果对象由其他账号上传且仍依赖旧 ACL,所有权不一致也可能造成访问问题。

第五步:根路径 403 时检查默认根对象

如果 https://cdn.example.com/index.html 正常,但 https://cdn.example.com/ 返回 403,最可能的问题不是 OAC,而是没有设置默认根对象,或者填写格式错误。

在 CloudFront 分配的常规设置中,将默认根对象设置为:

index.html

不要填写:

/index.html

AWS 文档明确说明,默认根对象不能以正斜杠开头;使用 /index.html 可能导致 403 Access Denied。

默认根对象只自动处理分配根路径。假设默认根对象是 index.html,请求 /docs/ 时,CloudFront 不会自动改为 /docs/index.html。需要目录索引行为时,可以使用 CloudFront Function 重写 URI,或在应用构建阶段生成明确路径,但应先测试缓存键和重定向逻辑。

第六步:SSE-KMS 加密对象还需要密钥策略

如果 S3 对象使用 SSE-S3 加密,通常不需要额外的 KMS 权限;如果对象使用客户管理的 AWS KMS 密钥进行 SSE-KMS 加密,仅允许 s3:GetObject 可能仍然返回 403。

此时需要在 KMS 密钥策略中授权 CloudFront 服务主体,并用具体分配 ARN 限定来源。常见所需操作包括 kms:Decrypt,涉及通过 CloudFront 写入对象时还可能需要 kms:Encryptkms:GenerateDataKey*

排查方法:先查看出错对象的 Server-side encryption 字段。如果只有部分文件 403,而这些文件恰好使用了不同的 KMS 密钥,应优先检查对应密钥策略。

第七步:权限修复后清理已缓存的 403

CloudFront 会缓存部分错误响应。默认情况下,错误响应通常缓存 10 秒;如果自定义错误响应设置了更长的 Error Caching Minimum TTL,或者源站错误响应携带较长的 Cache-Control,权限修复后仍可能继续看到旧的 403。

先等待配置部署和错误缓存过期。如果需要立即验证,可以对具体路径创建缓存失效:

aws cloudfront create-invalidation \
  --distribution-id YOUR_DISTRIBUTION_ID \
  --paths "/index.html"

只失效实际出错的对象,通常比直接使用 /* 更稳妥。若大量对象都缓存了错误,再根据影响范围决定是否扩大失效路径。

对于 S3 源,即使把错误缓存最小 TTL 设置为 0,CloudFront 对 S3 源错误仍可能保留至少 1 秒,以帮助保护源站。

其他会让 CloudFront 返回 403 的配置

当 S3 权限和对象路径都正确时,还要检查 CloudFront 自身是否主动拒绝了请求:

  • AWS WAF:规则、速率限制或托管规则组可能拦截请求。

  • 地理限制:被限制国家或地区的用户会收到 403。

  • 签名 URL 或签名 Cookie:启用 Restrict viewer access 后,缺少有效签名的请求会返回 403。

  • 错误的 Host 头转发:向 S3 REST API 端点转发不匹配的查看器 Host 头可能导致错误。

  • CloudFront 套 CloudFront:AWS 不建议把多个 CloudFront 分配串联,堆叠分配可能返回 403。

  • 不允许的 HTTP 方法:行为只允许 GET/HEAD 时,PUT、POST 或 DELETE 请求不会按预期到达 S3。

推荐的 CloudFront S3 403 排查顺序

  1. 请求根路径和一个确定存在的文件,确认故障范围。

  2. 确认对象键存在,并检查路径、大小写和 Origin Path。

  3. 确认源是普通 S3 存储桶端点,而不是误用网站端点。

  4. 确认 OAC 已绑定到当前源,并使用推荐的始终签名设置。

  5. 核对存储桶策略中的 Principal、Resource、账号 ID 和分配 ID。

  6. 检查显式 Deny、对象所有权和跨账号上传问题。

  7. 如果使用 SSE-KMS,检查对应 KMS 密钥策略。

  8. 根路径单独失败时,检查默认根对象且不要添加开头斜杠。

  9. 检查 WAF、地理限制、签名访问和 HTTP 方法设置。

  10. 等待分配部署完成,并清除必要的错误缓存。

常见问题

修复 CloudFront 403 必须公开 S3 存储桶吗?

不需要。普通 S3 存储桶可以保持 Block Public Access,通过 OAC 和限定具体分配 ARN 的存储桶策略授权 CloudFront 读取对象。

OAC 和 OAI 应该选哪个?

新配置优先使用 OAC。AWS 推荐 OAC,因为它支持所有 S3 区域、SSE-KMS 和动态 S3 请求等能力。OAI 属于旧方式,主要用于兼容已有配置。

为什么 S3 控制台里能看到文件,CloudFront 仍然返回 403?

控制台访问使用的是当前登录用户的 IAM 权限,CloudFront 访问使用 OAC 签名和存储桶策略。两者身份不同,因此“管理员能看到文件”不能证明 CloudFront 已获得读取权限。

为什么不存在的 S3 文件有时返回 403,而不是 404?

私有 S3 源不会总是向请求方暴露对象是否存在。AWS 的 CloudFront 故障排查文档也指出,缺少对象或对象名称大小写错误可能表现为 Access Denied。

设置 index.html 后,为什么 /docs/ 仍然不显示 docs/index.html?

CloudFront 默认根对象主要用于分配根 URL,不会自动为每个子目录查找 index.html。子目录索引需要单独的 URI 重写、应用路由或静态站点方案。

修改权限后需要多久生效?

S3 和 KMS 策略修改通常很快,但 CloudFront 分配配置需要完成全球部署,旧的 403 还可能受错误缓存 TTL 影响。应先等待部署完成,再根据需要失效具体对象。

结论

CloudFront 访问 S3 返回 403 时,应先区分“所有对象失败、根路径失败、单个对象失败还是旧错误被缓存”。对于私有内容,正确架构通常是普通 S3 存储桶、开启 Block Public Access、使用 OAC 始终签名,并在存储桶策略中只允许指定 CloudFront 分配读取对象。

如果具体文件正常而根路径失败,优先修复默认根对象;如果只有加密文件失败,检查 KMS 密钥策略;如果权限已经修好但仍报错,等待错误缓存过期或失效对应路径。按照这个顺序排查,可以避免通过公开存储桶来“临时解决”权限问题。

CloudFlew 提供基于 AWS CloudFront 的 CDN 服务。部署私有 S3 源时,应同时核对 CloudFront 源配置、OAC、S3 存储桶策略、默认根对象和缓存行为,避免只处理其中一个环节。

参考资料

  1. AWS CloudFront 开发者指南:限制对 Amazon S3 源的访问,核查日期:2026-07-31

  2. AWS CloudFront 开发者指南:指定默认根对象,核查日期:2026-07-31

  3. AWS CloudFront 开发者指南:排查分配问题,核查日期:2026-07-31

  4. AWS CloudFront 开发者指南:HTTP 403 Permission Denied,核查日期:2026-07-31

  5. AWS CloudFront 开发者指南:控制错误缓存时间,核查日期:2026-07-31