将文件上传到 S3(法兰克福)获得错误授权 AWS4-HMAC-SHA256

Uploading a file to S3 (frankfurt) gets an error authorization AWS4-HMAC-SHA256

您好 :) 当我尝试直接将文件上传到 AWS S3 时,出现此错误:

The authorization mechanism you have provided is not supported. Please use AWS4-HMAC-SHA256.

好像我在签署 v4 hmac 授权签名时遗漏了一些东西:\

html 文件:

<form action="https://mybucket.s3.eu-central-1.amazonaws.com/" enctype="multipart/form-data" id="form-upload" method="POST">
    <input type="hidden" name="AWSAccessKeyId" value="myPublicKey">
    <input type="hidden" name="acl" value="private">
    <input type="hidden" name="success_action_redirect" value="http://localhost:8080/uploadAfter">
    <input type="hidden" name="Content-type" value=""> <!-- any file format -->
    <input type="hidden" name="x-amz-algorithm" value="AWS4-HMAC-SHA256">

    <!-- The following are injected by Javascript -->
    <input type="hidden" name="key">
    <input type="hidden" name="policy">
    <input type="hidden" name="signature">
    <input type="hidden" name="x-amz-credential">
    <input type="hidden" name="x-amz-date">
    <input type="hidden" name="x-amz-signature">

    <input type="file" id="inputFile">
    <button id="form-upload-submit" type="submit">Upload</button>
</form>

服务器端Node文件("getS3Credentials ajax request"):

var crypto = require("crypto"),

AWS_ACCESS_KEY = process.env.AWS_ACCESS_KEY,
AWS_SECRET_KEY = process.env.AWS_SECRET_KEY,

dateNow = new Date().toISOString(),     
dateNowRaw = dateNow.substr(0, dateNow.indexOf("T")).replace(/-/g, ""),

expiration = new Date();
expiration.setHours(expiration.getHours() + 1);
expiration = expiration.toISOString();

var policy = {
    expiration: expiration,
    conditions: [
        {bucket: "mybucket"},
        ["starts-with", "$key", "files/filename"],
        {acl: "private"},
        {success_action_redirect: "http://localhost:8080/uploadAfter"},
        ["starts-with", "$Content-Type", ""],
        ["content-length-range", 0, 1024*1024*100],
        {"x-amz-algorithm": "AWS4-HMAC-SHA256"},
        {"x-amz-credential": AWS_ACCESS_KEY + "/" + dateNowRaw + "/eu-central-1/s3/aws4_request"},
        {"x-amz-date": dateNow}
    ],        
},

policyString = JSON.stringify(policy),
encodedPolicyString = new Buffer(policyString, "utf-8").toString("base64"),

dateKey = app.crypto
    .createHmac("sha256", "AWS4" + AWS_SECRET_KEY)
    .update(dateNowRaw)
    .digest('binary'),

dateRegionKey = app.crypto
    .createHmac("sha256", dateKey)
    .update("eu-central-1")
    .digest('binary'),

dateRegionServiceKey = app.crypto
    .createHmac("sha256", dateRegionKey)
    .update("s3")
    .digest('binary'),

signinKey = app.crypto
    .createHmac("sha256", dateRegionServiceKey)
    .update("aws4_request")
    .digest('binary'),

signature = app.crypto
    .createHmac("sha256", signinKey)
    .update(encodedPolicyString)
    .digest('base64');

$.send({awskeyid: AWS_ACCESS_KEY, s3_policy: encodedPolicyString, s3_signature: signature, s3_key: "files/filename", s3_date_now: dateNow, s3_date_now_raw: dateNowRaw});

客户端js文件:

document.getElementById("form-upload-submit").onclick = function(evt) {
    evt.preventDefault();
    formUpload();
};

function formUpload() {
    var xhr = new XMLHttpRequest(); 
    xhr.open("POST", "/upload");
    xhr.responseType = "json";      
    xhr.onload = processUpload;     
    xhr.send();
}

function processUpload() {
    var response = this.response;

    document.querySelector("#form-upload input[type='hidden'][name='key']").value = response.s3_key;
    document.querySelector("#form-upload input[type='hidden'][name='policy']").value = response.s3_policy;
    document.querySelector("#form-upload input[type='hidden'][name='signature']").value = response.s3_signature;
    document.querySelector("#form-upload input[type='hidden'][name='x-amz-credential']").value = response.awskeyid + "/" + response.s3_date_now_raw + "/eu-central-1/s3/aws4_request";
    document.querySelector("#form-upload input[type='hidden'][name='x-amz-date']").value = response.s3_date_now;

    document.getElementById("form-upload").submit();
    //The error is shown here as xml page, after the submitting of the form with the redirect to the amazon upload url
}

感谢您的帮助 ;)

您应该从表单中删除字段 'AWSAccessKeyId'。
看来,如果您将此字段添加到表单中,AWS 会尝试使用 SHA1 验证签名并忽略您提到的算法类型。

看看这个aws post example, and check that the fields in your form matches the aws form (you can use this tool

另一种选择是使用 SHA1 哈希