AWS CloudFront忽略默认根对象返回Access Denied问题求助
CloudFront默认根对象对子路径无效的问题解析
问题根源
CloudFront的默认根对象设置只对分发的根路径(/)生效,没法自动处理子目录路径(比如/foo/bar/)。当你访问http://example.com/foo/bar/时,CloudFront会直接把这个路径转发给S3,而S3本身不会自动查找该路径下的index.html,所以返回Access Denied;但直接访问/foo/bar/index.html时,请求的是明确的对象键,S3能正常返回内容。
解决办法
可以通过请求重写来实现子目录自动指向index.html,推荐两种低成本方案:
方案1:CloudFront函数(优先选,成本更低、响应更快)
创建一个CloudFront函数,代码逻辑如下:
function handler(event) { const request = event.request; const uri = request.uri; // 给以/结尾的路径追加index.html if (uri.endsWith('/')) { request.uri += 'index.html'; } return request; }
创建完成后,把这个函数关联到CloudFront分发的Viewer Request事件,绑定到对应的行为上即可。
方案2:Lambda@Edge(适合复杂逻辑场景)
如果需要更灵活的处理逻辑,可以用Lambda@Edge(注意Lambda必须部署在us-east-1区域),示例代码:
exports.handler = (event, context, callback) => { const request = event.Records[0].cf.request; const uri = request.uri; if (uri.endsWith('/')) { request.uri += 'index.html'; } callback(null, request); };
将该Lambda函数关联到CloudFront分发的Viewer Request事件类型。
额外验证项
- 确认S3桶中存在
foo/bar/index.html这个对象(S3是扁平存储,不存在真实目录,foo/bar/index.html是完整的对象键)。 - 检查CloudFront的缓存策略,确保重写后的请求能被正确缓存,减少函数触发次数。
内容的提问来源于stack exchange,提问作者Philip Couling
相关产品推荐
相关产品推荐

