S3预签名URL报错:请求含未签名标头,寻求技术协助
解决S3预签名URL“请求中存在未签名的标头”错误
这个错误的核心原因是:生成预签名URL时,没有将请求实际发送的某些HTTP头包含在签名范围里,S3收到请求时发现有未被签名的头,就会拒绝访问。以下是具体的解决步骤:
1. 在预签名参数中显式声明需要签名的请求头
浏览器发起GET请求时,通常会自动带上Accept、Accept-Encoding等头,你需要把这些头添加到预签名的参数中,确保签名覆盖这些头:
修改你的s3Params对象,添加Headers字段:
const s3Params = { Bucket: process.env.UploadBucket, Key: `${orderId}.pdf`, Expires: parseInt(process.env.URLExpirationsSeconds), // 添加浏览器常见的请求头,确保签名包含这些头 Headers: { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br' } }
如果你的前端请求还会发送其他自定义头,也要把这些头加到Headers里。
2. 验证S3桶的CORS配置
确保你的S3桶CORS策略允许这些请求头和GET方法,示例CORS配置如下(生产环境建议限制具体域名):
<CORSConfiguration> <CORSRule> <AllowedOrigin>*</AllowedOrigin> <AllowedMethod>GET</AllowedMethod> <AllowedHeader>Accept</AllowedHeader> <AllowedHeader>Accept-Encoding</AllowedHeader> <AllowedHeader>Authorization</AllowedHeader> <MaxAgeSeconds>3000</MaxAgeSeconds> </CORSRule> </CORSConfiguration>
3. 检查AWS SDK版本
确保你使用的aws-sdk包是最新的v2版本,旧版本可能存在签名逻辑的bug。执行以下命令更新:
npm update aws-sdk
修正后的完整代码
const AWS = require("aws-sdk"); const s3 = new AWS.S3(); exports.handler = async (event) => { return await getUploadURL(event) } const getUploadURL = async function(event) { const orderId = event.orderId; const s3Params = { Bucket: process.env.UploadBucket, Key: `${orderId}.pdf`, Expires: parseInt(process.env.URLExpirationsSeconds), // 添加需要签名的请求头 Headers: { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, br' } } console.log('Params: ', s3Params) try { const uploadURL = await s3.getSignedUrlPromise('getObject', s3Params) return { statusCode: 200, body: JSON.stringify({ uploadURL: uploadURL, }) } } catch (error) { console.error(error); let errorMessage; if (error instanceof Error) { errorMessage = error.message; } else { errorMessage = 'An unknown error occurred'; } return { statusCode: 500, body: JSON.stringify({ message: "Could not generate the presigned URL", error: errorMessage, }), }; } }
内容的提问来源于stack exchange,提问作者Adamovichhh
相关产品推荐
相关产品推荐

