簡體   English   中英

Amazon S3 POST api,並使用 NodeJS 簽署策略

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM