Heroku环境下Django Compressor+AWS CloudFront本地资源加载Access Denied问题求助
我之前配置Django Compressor搭配CloudFront和S3时也踩过类似的坑,给你几个具体的排查方向:
检查S3桶策略,别只依赖文件夹权限
单独设置文件夹"公开可见"有时候不生效,因为S3的权限优先级是桶策略 > 文件夹权限 > 对象权限。你需要确保桶策略允许对压缩资源路径的读取权限:
如果是公开访问(适合静态资源),可以添加这样的桶策略:{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的存储桶名称/static/CACHE/*" } ] }如果你用了CloudFront的Origin Access Identity(OAI),则需要把权限给这个OAI,而不是所有用户:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity 你的OAI ID" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的存储桶名称/static/CACHE/*" } ] }确认CloudFront OAI的配置是否正确
如果你启用了OAI,必须确保S3桶的权限是授予给这个OAI的,同时CloudFront的源配置里要勾选"限制桶访问",并选择对应的OAI。很多人会犯的错误是:开了OAI但没给S3桶授权,或者直接公开S3桶但CloudFront用了OAI,导致权限冲突。验证Django Compressor的配置细节
检查你的settings.py里的关键配置:COMPRESS_STORAGE是否设置为S3存储后端(比如storages.backends.s3boto3.S3Boto3Storage)COMPRESS_URL是否指向你的CloudFront域名(而不是S3的直接域名)STATICFILES_STORAGE是否和COMPRESS_STORAGE保持一致,避免静态资源存储位置不一致- 本地开发时是否开启了
COMPRESS_ENABLED = True(默认本地可能关闭,导致生成的链接不符合预期)
刷新CloudFront缓存,避免旧错误被缓存
CloudFront会缓存错误响应(比如403),即使你后来修复了S3权限,浏览器可能还是会拿到缓存的错误。可以手动在CloudFront控制台刷新/static/CACHE/*路径的缓存,或者用命令行工具操作。检查单个S3对象的实际权限
有时候文件夹的权限设置不会自动继承给已存在的文件。你可以进入S3控制台,找到那个显示Access Denied的CSS文件,查看它的权限是否允许读取(比如公共读取,或者OAI的读取权限)。如果没有,手动修改或者重新运行压缩命令生成新的文件。用工具排查请求细节
打开浏览器开发者工具的Network面板,找到那个失败的CSS请求,查看响应头部:- 确认错误是来自S3还是CloudFront(响应头里的
Server字段会显示AmazonS3或者CloudFront) - 查看
x-amz-error-code字段,S3会返回具体的错误码(比如AccessDenied、NoSuchBucket等),帮助定位问题
- 确认错误是来自S3还是CloudFront(响应头里的
内容的提问来源于stack exchange,提问作者John Rogerson

