SignatureDoesNotMatch browser based upload to s3

2019-02-27 23:08发布

问题:

I know many asked this question and I looked into their post but I still never got the correct answer so here goes.

I'm trying to upload an image to s3 using the Browser Based uploading technique introduce by Amazon dev. Right now I'm able to calculate both policy & signature on my end. But when I tried to upload an image I always get a "Signature not match" (>.<). One main problem I'm having is that the credentials I have are just temporary: AWS Security Token Service, this consist of an accessKEy, secretKey and security token. I'll post my code so anyone please

Here's my policy_json conversion

function setValues(accesskey, secretkey, token) {
      var folder = 'avatars/email@domain.com/',
          acl = 'public-read', 
          bucket = 'my-bucket';

      var POLICY_JSON = { "expiration": "2013-12-03T12:29:27.000Z",
          "conditions": [
            {"bucket": bucket},
            ["starts-with", "$key", folder],
            {"acl": acl},
            {"success_action_redirect": "201"},
            ["starts-with", "$Content-Type", "image/png"]
          ]
        };
      var policy = Base64.encode(JSON.stringify(POLICY_JSON));
      var signature = b64_hmac_sha1(secretkey, policy);

      return {
          "policy":policy, 
          "signature":signature,
          "folder" : folder,
          "acl" : acl,
          "bucket" : bucket
        }
    }

My upload

function upload(acl, accesskey, policy, signature, token) {
  $(':button').click(function()
  {
    var file = document.getElementById('file').files[0];
     // var key = "events/" + (new Date).getTime() + '-' + file.name;
    var xdate = '20131016T105000Z';
    // var formData = new FormData($('form')[0]); //$('form')[0]
    var formData = new FormData(); //$('form')[0]
    formData.append("key", "avatars/email@domain.com/${filename}");
    formData.append("acl", acl);
    formData.append("success_action_redirect", "201");
    formData.append("Content-Type", file.type);
    formData.append("AWSAccessKeyId", accesskey);
    formData.append("policy", policy);
    formData.append("signature", signature);
    // formData.append("x-amz-security-token", token);
    formData.append("file", file);
    $.ajax({
        url: 'https://mybucket.s3.amazonaws.com',  //Server script to process data
        type: 'POST',
        xhr: function() {  // Custom XMLHttpRequest
            var myXhr = $.ajaxSettings.xhr();
            if(myXhr.upload){ // Check if upload property exists
                myXhr.upload.addEventListener('progress',progressHandlingFunction, false); // For handling the progress of the upload
            }
            return myXhr;
        },
        //Ajax events
        beforeSend: function(e) { 
          e.setRequestHeader("Authorization", "AWS "+accesskey+":"+signature);
          e.setRequestHeader("x-amz-date", xdate);
          e.setRequestHeader("x-amz-acl", acl);
          e.setRequestHeader("x-amz-security-token", token);

          // alert('Are you sure you want to upload document.'); 
        },
        success: function(e) { alert('Upload completed'); } ,
        error: function(jqXHR, textStatus, errorThrown) { 
          console.log(textStatus);
          console.log(errorThrown);
        } ,
        // Form data
        data: formData,
        //Options to tell jQuery not to process data or worry about content-type.
        cache: false,
        contentType: false,
        processData: false
    });
  });
}

My only html

<form enctype="multipart/form-data">
    <input id="file" name="file" type="file" />
    <input type="button" value="Upload" />
</form>

This is what confused me, at first inside the mybucket it has a folder named avatars now when my colleague uploaded an image (say image1.jpg) using his email_address (say other_email_Address@domain.com) and the uploading is successful when we look at the bucket it created a folder with the name of his email_address and inside it the image. Why is that?

mybucket/
 - avatars/
  - my_email_address.@domain.com
    - image1
  - other_email_address@domain.com
    - image1
  so on ...

the tools i used are: webtoolkit.base64.js, sha1.js, base64-binary.js.