[英]Amazon S3 POST api, and signing a policy with NodeJS
我正在嘗試構建允許用戶從 NodeJS 支持的網站將文件直接上傳到我的 Amazon S3 存儲桶的構建。 除了實際的亞馬遜文檔之外,似乎唯一的教程都非常過時。
我一直在關注本教程,了解基本信息,但它又過時了。 它沒有對crypto
正確的方法調用,因為它試圖將原始 JavaScript 對象傳遞給update
方法,這會引發錯誤,因為它不是字符串或緩沖區。
我也一直在查看knox npm 包的來源。 它沒有內置的 POST 支持——我完全理解,因為瀏覽器一旦擁有正確的字段就會執行 POST。 Knox 似乎確實有正確的代碼來簽署政策,我試圖讓我的代碼基於此工作......但再次無濟於事。
這是我想出的代碼。 它生成一個 base64 編碼的策略,並創建一個簽名......但根據亞馬遜的說法,當我嘗試上傳文件時,這是錯誤的簽名。
var crypto = require("crypto");
var config = require("../../amazonConfig.json");
exports.createS3Policy = function(callback) {
var date = new Date();
var s3Policy = {
"expiration": "2014-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read"},
["content-length-range", 0, 2147483648],
{"bucket": "signalleaf"},
["starts-with", "$Cache-Control", ""],
["starts-with", "$Content-Type", ""],
["starts-with", "$Content-Disposition", ""],
["starts-with", "$Content-Encoding", ""],
["starts-with", "$Expires", ""],
["starts-with", "$key", "/myfolder/"],
{"success_action_redirect": "http://example.com/uploadsuccess"},
]
};
var stringPolicy = JSON.stringify(s3Policy).toString("utf-8");
var buffer = Buffer(stringPolicy, "utf-8");
var encoded = buffer.toString("base64");
var signature = crypto.createHmac("sha1", config.secretKey)
.update(new Buffer(stringPolicy, "utf-8")).digest("base64");
var s3Credentials = {
s3PolicyBase64: encoded,
s3Signature: signature
};
GLOBAL.s3creds = s3Credentials;
callback(s3Credentials);
};
我顯然做錯了什么,在這里。 但我不知道是什么。 誰能幫助確定我做錯了什么? 我的問題在哪里? 有沒有人有關於如何從 NodeJS v0.10.x 生成正確的帶有簽名的 Amazon S3 策略的工作教程,用於 POST 到 s3 REST api?
好吧,我終於想通了。 玩了很長時間的隨機猜謎游戲后,我心里想
“也許我需要簽署 base64 編碼策略” - 我
和BAM就是這樣。
我還重新排序了條件以匹配表單的發布方式,盡管我不確定這是否有所不同。
var crypto = require("crypto");
var config = require("../../amazonConfig.json");
exports.createS3Policy = function(contentType, callback) {
var date = new Date();
var s3Policy = {
"expiration": "2014-12-01T12:00:00.000Z", // hard coded for testing
"conditions": [
["starts-with", "$key", "somefolder/"],
{"bucket": "my-bucket-name"},
{"acl": "public-read"},
["starts-with", "$Content-Type", contentType],
{"success_action_redirect": "http://example.com/uploadsuccess"},
]
};
// stringify and encode the policy
var stringPolicy = JSON.stringify(s3Policy);
var base64Policy = Buffer(stringPolicy, "utf-8").toString("base64");
// sign the base64 encoded policy
var signature = crypto.createHmac("sha1", config.secretKey)
.update(new Buffer(base64Policy, "utf-8")).digest("base64");
// build the results object
var s3Credentials = {
s3Policy: base64Policy,
s3Signature: signature
};
// send it back
callback(s3Credentials);
};
希望這會幫助遇到同樣問題的其他人。
我修改了之前的一個例子,因為它對我不起作用:亞馬遜返回了一個關於簽名損壞的錯誤。
以下是使用 POST(AWS 簽名版本 4)為基於瀏覽器的上傳創建簽名的方法
http://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-authentication-HTTPPOST.html
var CryptoJS = require("crypto-js");
var accessKeyID = "PUT YOUR DATA";
var secretAccessKey = "PUT YOUR DATA";
var bucket = "PUT YOUR BUCKET NAME";
var region = "eu-central-1"; // overwrite with your region
var folder = "users/"; // overwrite with your folder
var expiration = "2015-09-28T12:00:00.000Z"; // overwrite date
var date = "20150927"; // overwrite date
var serviceName = "s3";
function getSignatureKey(key, dateStamp, regionName, serviceName) {
var kDate = CryptoJS.HmacSHA256(dateStamp, "AWS4" + key);
var kRegion = CryptoJS.HmacSHA256(regionName, kDate);
var kService = CryptoJS.HmacSHA256(serviceName, kRegion);
var kSigning = CryptoJS.HmacSHA256("aws4_request", kService);
return kSigning;
}
var s3Policy = {"expiration": expiration,
"conditions": [
{"bucket": bucket},
["starts-with", "$key", folder],
{"acl": "public-read"},
["starts-with", "$Content-Type", "image/"],
{"x-amz-meta-uuid": "14365123651274"},
["starts-with", "$x-amz-meta-tag", ""],
{"x-amz-credential": accessKeyID + "/" + date + "/" + region + "/" + serviceName +"/aws4_request"},
{"x-amz-algorithm": "AWS4-HMAC-SHA256"},
{"x-amz-date": date + "T000000Z" }
]
};
var base64Policy = new Buffer(JSON.stringify(s3Policy), "utf-8").toString("base64");
console.log('base64Policy:', base64Policy);
var signatureKey = getSignatureKey(secretAccessKey, date, region, serviceName);
var s3Signature = CryptoJS.HmacSHA256(base64Policy, signatureKey).toString(CryptoJS.enc.Hex);
console.log('s3Signature:', s3Signature);
接下來生成的 base64Policy 和 s3Signature 我在上傳表單中使用。 示例在這里: http : //docs.aws.amazon.com/AmazonS3/latest/API/sigv4-post-example.html
非常重要的是檢查您在 html 表單和策略中是否具有相同的字段和值。
我仍然遇到問題,所以我解決了這些問題並在此處發布了我的解決方案:
https://github.com/nikkwong/ng2-s3-uploader
簡而言之,如果您在構建簽名時使用 scabbiaza 的答案,請確保構建如下表單:
let formData = new FormData;
formData.append('acl', xAmzAcl);
formData.append('Content-Type', file.type);
formData.append('X-Amz-Date', xAmzDate);
formData.append('x-amz-server-side-encryption', xAmzServerSideEncryption);
formData.append('x-amz-meta-uuid', xAmzMetaUuid);
formData.append('X-Amz-Algorithm', xAmzAlgorithm);
formData.append('X-Amz-Credential', xAmzCredential);
formData.append('X-Amz-Signature', s3Signature);
formData.append('Policy', base64Policy);
formData.append('key', folder + '/' + file.name);
// File field must come last!
formData.append('file', file);
AWS 開發工具包現在提供了一種使用createPresignedPost()
創建 POST 策略的簡單方法。
文檔: https : //docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#createPresignedPost-property
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.