使用CloudFront Signed Cookies时遭遇访问拒绝错误
这个问题在互联网上已被多次提问和解答,但尝试几乎所有相关帖子后仍遇到问题,已经困扰我一个月了!
架构配置
我用S3 bucket存储前端流媒体服务的视频文件,通过CloudFront Distribution提供服务。为保障访问安全,搭建了API Gateway转发请求到自定义Lambda,获取CloudFront的Signed Cookies。
各服务单独测试均成功:
- 将S3访问权限设为公开,直接从S3请求
*.m3u8视频清单可正常播放(流媒体流畅)。 - 为CloudFront分发配置自定义SSL证书(避免CORS问题)后,通过CloudFront请求同一文件也正常。
- 由于前端需要访问S3上的整个文件夹(用于流媒体),据我理解唯一方式是用签名Cookie请求,因此搭建自定义Lambda返回CloudFront域名的
Set-Cookie头部。 - 为返回自定义头部,需通过API Gateway关联Lambda实现。
需强调:S3、CloudFront、Lambda和API Gateway单独运行均正常,但附加Cookie后就出现问题!
因此我猜测Cookie签名环节存在问题。
自定义Lambda代码
Lambda是Cookie签名的核心,以下为最简实现示例。基于Node JS编写,使用版本为"@aws-sdk/cloudfront-signer": "^3.229.0"。
const url = `https://my-cloudfront.domian.com/path-to-src/*`; const expTime = new Date(Date.now() + 5 * (60 * 60 * 1000)).toISOString(); const signedCookie = getSignedCookies({ keyPairId: awsCloudfrontKeyPairId, // 来自CloudFront配置 privateKey: awsCloudfrontPrivateKey, // 来自CloudFront配置 url: url, dateLessThan: getExpTime, }); const response = { statusCode: 200, isBase64Encoded: false, body: JSON.stringify({ url: url, bucket: bucket, key: key }), headers: { "Content-Type": "application/json", "Access-Control-Allow-Origin": "*", "Access-Control-Allow-Credentials": true, "Access-Control-Allow-Methods": "OPTIONS,POST,GET", }, multiValueHeaders: { "Set-Cookie": [ `CloudFront-Expires=${signedCookie["CloudFront-Expires"]}; Domain=domain.com; Path=/*`, `CloudFront-Signature=${signedCookie["CloudFront-Signature"]}; Domain=domain.com; Path=/*`, `CloudFront-Key-Pair-Id=${signedCookie["CloudFront-Key-Pair-Id"]}; Domain=domain.com; Path=/*`, ], }, }; callback(null, response);
我能获取3个Set-Cookie头部,请求文件时也会提交这些Cookie,但结果始终返回:
ACCESS DENIED
测试步骤
我对各服务进行了以下测试:
- 仅使用S3 → 流媒体正常播放
- 关闭
viewer restriction的CloudFront → 流媒体正常播放 - 开启
viewer restriction但无Cookie的CloudFront → 出现Missing Key错误 - 开启
viewer restriction并携带Cookie的CloudFront → 出现Access Denied错误
显然还有诸多重要配置步骤(如存储桶策略、自定义域名等)未提及,若需可补充提供。
内容的提问来源于stack exchange,提问作者Flo Ragossnig
相关产品推荐
相关产品推荐

