Amazon S3 POST API以及使用NodeJS签署策略

我试图build立一个允许用户从NodeJS支持的网站直接上传文件到我的Amazon S3存储桶的内置程序。 这里似乎只有教程,除了实际的亚马逊文件,这是非常过时的。

我一直在关注这个教程 ,获取基本的信息,但是它又是过时的。 它没有方法调用crypto正确,因为它试图传递一个原始的JavaScript对象的update方法,由于它不是一个string或缓冲区抛出一个错误。

我也一直在看knox npm包的源代码。 它没有内置的POST支持 – 我完全理解,因为它是浏览器一旦拥有正确的字段就进行POST。 诺克斯似乎有正确的代码来签署一个政策,我试图让我的代码基于这个工作…但再次无济于事。

这是我为了代码而想出来的。 它产生一个base64编码策略,它创build一个签名…但是当我尝试做一个file upload的时候,它是根据Amazon的错误签名。

 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); }; 

在这里,我显然做错了什么。 但我不知道是什么。 任何人都可以帮助确定我做错了什么? 我的问题在哪里? 有没有人有一个工作的教程,如何生成一个适当的亚马逊S3策略,签名,从NodeJS v0.10.x,一个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); }; 

希望这能帮助那些遇到同样问题的人。

我修改了前面的一个例子,因为它不适用于我:amazon返回了有关破坏签名的错误。

以下是如何使用POST(AWS签名版本4)为基于浏览器的上传创build签名

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表单和你的策略中有相同的字段和值。

我仍然有问题,所以我通过他们,并在这里贴出我的解决scheme:

https://github.com/nikkwong/ng2-s3-uploader

简而言之,如果你用scabbiaza的答案来build立签名,一定要像这样构build表单:

 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);