部署在AWS S3的NextJS应用刷新页面出现AccessDenied错误如何解决?
解决方案
该问题是静态导出的NextJS单页应用的典型问题:页面内跳转由前端路由接管,没有真实请求S3资源;刷新时浏览器会请求对应路径的S3对象,不存在对应文件就会返回AccessDenied错误。
前置配置校验
首先确保next.config.js已经添加静态导出和尾部斜杠配置,重新构建导出后再上传S3,该配置同时也能解决根路径需要手动输入index.html才能访问的问题:
/** @type {import('next').NextConfig} */ const nextConfig = { // 开启静态导出 output: 'export', // 所有页面生成为目录下的index.html, 如/about生成为/about/index.html trailingSlash: true, } module.exports = nextConfig
方案1:仅使用S3静态网站托管(未搭配CloudFront)
- 进入S3存储桶的「属性」页,找到「静态网站托管」配置项
- 确认已开启静态网站托管,索引文档和错误文档均填写
index.html - 如仍报错,添加如下重定向规则,将403/404请求重定向到前端入口:
[ { "Condition": { "HttpErrorCodeReturnedEquals": "403" }, "Redirect": { "ReplaceKeyWith": "index.html", "HttpRedirectCode": "200" } }, { "Condition": { "HttpErrorCodeReturnedEquals": "404" }, "Redirect": { "ReplaceKeyWith": "index.html", "HttpRedirectCode": "200" } } ]
- 确认S3桶策略已开放公开读权限(仅适用于直接用S3对外提供访问的场景),桶策略示例:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::你的桶名称/*" } ] }
方案2:搭配CloudFront CDN使用(推荐)
该方案安全性和访问速度更优,无需开放S3公开访问权限:
- 进入CloudFront分发的「错误页面」配置页,新建自定义错误响应
- 分别为403、404错误码添加配置:
- 自定义错误响应:开启
- 响应页面路径:
/index.html - HTTP响应码:
200 OK
- 保存配置后等待CloudFront分发生效(通常耗时5-10分钟)
- 确认已经配置CloudOrigin Access Control(OAC),允许CloudFront访问S3桶内资源
补充排查点
- 确认上传到S3的文件权限配置正确,使用CLI同步时可添加
--acl public-read参数(仅适用于S3公开访问场景) - 确认NextJS静态导出无报错,所有路由均已生成对应的静态html文件
内容的提问来源于stack exchange,提问作者Blueboye
相关产品推荐
相关产品推荐

