我正在尝试使用由Node.js后端生成的签名策略来授权基于浏览器的POST到Angular 6前端的S3。我使用的凭据绝对正确,可以成功使用来自后端的s3.putObject()
或s3.upload()
。我浏览了文档,并尝试了许多不同的方法,但是无论如何,我得到的这个血腥签名不匹配错误。
这是Chrome开发人员工具所显示的内容(出于明显原因,我将访问密钥替换为XXXXXXXXXXXXXXXXXXXX:
key: test
success_action_status: 204
Content-Type: image/tiff; charset=UTF-8
X-Amz-Credential: XXXXXXXXXXXXXXXXXXXX/20181024T144545679Z/us-east-1/s3/aws4_request
X-Amz-Algorithm: AWS4-HMAC-SHA256
X-Amz-Date: 20181024T144545679Z
Policy: eyJleHBpcmF0aW9uIjoiMjAxOC0xMC0yNFQxNTo0NTo0NS42NzlaIiwiY29uZGl0aW9ucyI6W3siYnVja2V0Ijoid21nLWZhc3QtdHJhY2stcWEtbWVkaWEifSxbInN0YXJ0cy13aXRoIiwiJENvbnRlbnQtVHlwZSIsImltYWdlLyJdLHsia2V5IjoidGVzdCJ9LHsieC1hbXotYWxnb3JpdGhtIjoiQVdTNC1ITUFDLVNIQTI1NiJ9LHsieC1hbXotY3JlZGVudGlhbCI6IkFLSUFKS1dKTzZBTzdBVFRPQktRLzIwMTgxMDI0VDE0NDU0NTY3OVovdXMtZWFzdC0xL3MzL2F3czRfcmVxdWVzdCJ9LHsieC1hbXotZGF0ZSI6IjIwMTgxMDI0VDE0NDU0NTY3OVoifSx7InN1Y2Nlc3NfYWN0aW9uX3N0YXR1cyI6IjIwNCJ9XX0=
X-Amz-Signature: 067960dfb2607b69b078eb625b63f2659d47f2e4c2b5af4dc135c5f317492e8e
file: (binary)
这是扩展和字符串化后的JSON策略的样子:
{
"expiration": "2018-10-24T15:41:28.737Z",
"conditions": [
{
"bucket": "wmg-fast-track-qa-media"
},
[
"starts-with",
"$Content-Type",
"image/"
],
{
"key": "test"
},
{
"x-amz-algorithm": "AWS4-HMAC-SHA256"
},
{
"x-amz-credential": "XXXXXXXXXXXXXXXXXXXX/20181024T144128737Z/us-east-1/s3/aws4_request"
},
{
"x-amz-date": "20181024T144128737Z"
},
{
"success_action_status": 204
}
]
}
接下来,我将显示Node.js / Express路由,该路由生成签名的策略和签名。该路由在底部调用getCredentials()
函数,该函数调用其他函数以生成凭据:
'use strict';
const moment = require('moment');
const sha256 = require('js-sha256');
const utf8 = require('utf8');
const BUCKET = process.env.AWS_BUCKET_NAME;
const AWS_ACCESS_KEY_ID = process.env.AWS_ACCESS_KEY_ID;
const AWS_REGION = process.env.AWS_REGION;
const AWS_SECRET_ACCESS_KEY = process.env.AWS_SECRET_ACCESS_KEY;
async function hmac(key, secret) {
return sha256.hmac(key, secret)
}
async function hmacHex(key, secret) {
const hash = sha256.hmac.create(key);
hash.update(secret);
return hash.hex();
}
function getXAmzCredential(date) {
return `${AWS_ACCESS_KEY_ID}/${date}/${AWS_REGION}/s3/aws4_request`;
}
async function getStringToSign(date, type) {
const expDate = moment().add(1, 'h').toISOString();
const policy = {
"expiration": expDate,
"conditions": [
{"bucket": BUCKET},
["starts-with", "$Content-Type", `${type}/`],
{"key": "test"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-credential": getXAmzCredential(date)},
{"x-amz-date": date},
{"success_action_status": 204}
]
};
const str = utf8.encode(JSON.stringify(policy).replace(/\r/g, ''));
return new Buffer.from(str).toString('base64');
}
async function getSigningKey(date) {
const dateKey = await hmac("AWS4" + AWS_SECRET_ACCESS_KEY, date);
const dateRegionKey = await hmac(dateKey, AWS_REGION);
const dateRegionServiceKey = await hmac(dateRegionKey, "s3");
return await hmac(dateRegionServiceKey, "aws4_request");
}
async function getCredentials(req, res) {
const type = req.body.upload_type;
const date = moment().toISOString();
const d = date.replace(/[:.-]/g,'');
const stringToSign = await getStringToSign(d, type);
const signingKey = await getSigningKey(d);
const signature = await hmacHex(signingKey, stringToSign);
const credential = getXAmzCredential(d);
console.log(`x-amz-credential: ${credential}`);
const response = {
policy: stringToSign,
signature: signature,
date: d,
xamzCredential: credential
};
res.json(response);
}
module.exports = {
getCredentials
};
如果有人能看到我在这里做错的事情或有建议,请提前谢谢您。