使用Lambda@Edge和CloudFront为所有路由(含错误路由)添加HTTP安全头失效
问题根因
你当前的Lambda@Edge仅绑定了源响应事件,仅在CloudFront正常从S3获取到2xx/3xx响应时才会触发执行。而React Router的子路径请求发送到S3时,S3不存在对应路径的实体文件会直接返回404/403错误,CloudFront触发自定义错误响应返回index.html的流程属于错误响应链路,默认不会触发源响应阶段的Lambda,因此安全头无法注入。
解决方案
方案一:Lambda@Edge绑定双事件覆盖全场景
将你的Lambda同时绑定到源响应+查看器响应两个事件:
- 查看器响应事件会在CloudFront向用户返回所有响应(含正常响应、自定义错误响应)前触发,天然覆盖错误场景
- 无需修改现有注入逻辑,仅调整事件绑定配置即可,示例代码保持如下写法:
exports.handler = (event, context, callback) => { const response = event.Records[0].cf.response; const headers = response.headers; // 保留现有安全头注入逻辑 headers['x-frame-options'] = [{key: 'X-Frame-Options', value: 'DENY'}]; headers['x-xss-protection'] = [{key: 'X-XSS-Protection', value: '1; mode=block'}]; callback(null, response); };
- 注意:Lambda必须部署在us-east-1区域,调整执行角色权限适配查看器响应事件的调用要求,修改完成后发布Lambda新版本重新绑定到CloudFront,再做缓存失效即可。
方案二:调整路由配置从根源避免错误触发
修改S3+CloudFront的路由规则,让所有子路由请求都走正常响应链路:
- S3静态网站托管配置中,索引文档和错误文档统一设置为
index.html - CloudFront添加自定义错误页规则:对404、403错误码,自定义响应路径设置为
/index.html,返回响应码修改为200 - 配置完成后所有子路由请求都会正常返回index.html的200响应,直接触发你原本绑定在源响应事件的Lambda注入安全头,无需修改Lambda配置。
注意事项
- Lambda@Edge部署包大小不能超过1MB(查看器响应事件限制),不要包含region相关的硬编码配置
- CloudFront配置修改后最长需要15分钟完成全网部署,生效前不要重复提交修改
内容的提问来源于stack exchange,提问作者Alan
相关产品推荐
相关产品推荐

