如何修复AWS SignatureDoesNotMatch错误

时间:2018-10-24 15:37:41

标签: amazon-web-services authentication amazon-s3

我正在尝试使用由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
};

如果有人能看到我在这里做错的事情或有建议,请提前谢谢您。

0 个答案:

没有答案