You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

EC2托管网站访问S3公开URL返回403 Forbidden问题排查

问题:S3存储桶GET请求返回403 Forbidden,无法加载FontAwesome CSS文件

我正在开发一个Web应用,需要从Amazon S3获取自托管的FontAwesome资源(CSS文件),引入标签如下:

<link rel="stylesheet" href="https://docsbymario-env.s3.eu-north-1.amazonaws.com/fontawesome/css/all.min.css?v=1.0">

但浏览器控制台中,该GET请求返回403 Forbidden状态码。

我的S3存储桶策略明确允许托管网站的EC2实例(由Beanstalk环境创建)以及用于CodePipeline的IAM角色访问,策略语句如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowListBucketToRole",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::390527449299:role/DocsByMarioRole"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::docsbymario-env"
        },
        {
            "Sid": "AllowReadAccessToRole",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::390527449299:role/DocsByMarioRole"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::docsbymario-env/*"
        },
        {
            "Sid": "AllowListBucketToIPs",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::docsbymario-env",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "13.51.220.94/32",
                        "16.16.36.18/32"
                    ]
                }
            }
        },
        {
            "Sid": "AllowReadAccessToIP",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::docsbymario-env/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "13.51.220.94/32",
                        "16.16.36.18/32"
                    ]
                }
            }
        }
    ]
}

上述两个IP地址是我要加载CSS文件的EC2实例的公网IP。

我已为S3存储桶开启公共访问,CodePipeline可通过指定角色正常访问存储桶,但EC2无法通过上述基于IP的存储桶策略访问。

我曾认为是CORS相关问题,因此为存储桶添加了CORS策略:

[
    {
        "AllowedHeaders": [
            "*"
        ],
        "AllowedMethods": [
            "GET"
        ],
        "AllowedOrigins": [
            "http://docsbymario.com",
            "http://api.docsbymario.com"
        ],
        "ExposeHeaders": [
            "ETag"
        ],
        "MaxAgeSeconds": 3000
    }
]

其中两个域名实际指向上述两个公网IP,但问题仍未解决。

请问可能的问题是什么?


可能的排查方向

  • 源IP匹配错误:浏览器从EC2上的网站加载CSS时,请求的源IP是访问网站的用户客户端IP,而非EC2的公网IP。你存储桶策略里限制的是EC2的IP,自然匹配不上,导致403。
  • 单个对象权限未开放:存储桶策略允许访问,但all.min.css文件的ACL可能还是私有状态。检查该文件的对象权限,确认是否允许公共读取或对应角色/IP访问。
  • 存在其他权限冲突:AWS权限遵循“隐式拒绝”原则,如果账户有服务控制策略(SCP)或其他IAM策略限制了S3的GetObject操作,会覆盖当前存储桶策略的允许规则,需要排查这类限制。
  • 缓存导致的旧响应:之前的403响应可能被浏览器或CDN缓存,清除浏览器缓存或强制刷新页面后重试。
  • CORS策略未覆盖实际请求源:如果用户是用IP直接访问网站而非设置的域名,请求的Origin就不在AllowedOrigins列表中,虽然这一般是CORS报错而非403,但也可以确认请求头里的Origin值是否匹配。

内容的提问来源于stack exchange,提问作者Mario Mateaș

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 09:47:34