21

NodeJS を利用したウェブサイトから、ユーザーがファイルを Amazon S3 バケットに直接アップロードできるようにするビルドを取得しようとしています。これに関する実際のAmazonドキュメントを除いて、そこにある唯一のチュートリアルはすべて非常に古くなっているようです.

基本的な情報については、このチュートリアルに従っていますが、これも古くなっています。crypto生のJavaScriptオブジェクトをメソッドに渡そうとするため、修正するメソッド呼び出しがありませんupdate。これは、文字列でもバッファでもないため、エラーをスローします。

knox npm packageのソースも調べました。POST サポートが組み込まれていません。適切なフィールドがあれば、ブラウザが POST を実行するため、完全に理解しています。Knox はポリシーに署名するための適切なコードを持っているようです。私はこれに基づいてコードを機能させようとしましたが、やはり無駄でした。

これが私が思いついたコードです。それはbase64でエンコードされたポリシーを生成し、署名を作成します...しかし、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);
};

ここで私は明らかに何か間違ったことをしています。しかし、私には何がわかりません。誰かが私が間違っていることを特定するのを助けることができますか? 私の問題はどこですか?NodeJS v0.10.x から、s3 REST API への POST 用に、適切な Amazon S3 ポリシーを署名付きで生成する方法についての実用的なチュートリアルを持っている人はいますか?

4

4 に答える 4

36

わかりました、私はついにそれを理解しました。ランダムな推測ゲームを非常に長い間プレイした後、私は自分自身に考えました

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

うまくいけば、これは同じ問題に遭遇した他の人を助けるでしょう.

于 2013-08-28T02:03:11.333 に答える
19

うまくいかなかったので、前の例を少し修正しました。Amazon は壊れた署名に関するエラーを返しました。

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 フォームとポリシーに同じフィールドと値があることを確認することです。

于 2015-09-26T08:49:46.767 に答える
2

私は引き続き問題を抱えていたので、それらに取り組み、ここに私の解決策を投稿しました:

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);
于 2016-05-12T08:22:01.600 に答える