javascript - s3 "signature doesn't match" client side post jquery-file-upload -
i generating signature doing client side posting s3 in node on end , submitting via jquery-file-upload on client. signature generation looks following:
app.post('/api/v1/s3', function(req, res){ var data = utils.getreqjson(req.body); var mime_type = mime.lookup(data.filename); var expire = moment().utc().add('hour', 1).tojson("yyyy-mm-ddthh:mm:ss z"); var policy = json.stringify({ "expiration": expire, "conditions": [ {"bucket": aws_bucket}, ["starts-with", "$key", aws_bucket_dir], {"acl": "private"}, {"success_action_status": "201"}, ["starts-with", "$content-type", ''], ["content-length-range", 0, max_filesize] ] }); var base64policy = new buffer(policy).tostring('base64'); var signature = crypto.createhmac('sha1', process.env.aws_secret).update(base64policy).digest('base64'); signature = encodeuricomponent(signature.trim()); signature = signature.replace('%2b','+'); var file_key = uuid.v4(); res.json({ policy: base64policy, signature: signature, key: aws_bucket_dir + file_key + "_" + data.filename, contenttype: mime_type, aws_access: process.env.aws_access_key, bucket_dir: aws_bucket_dir, bucket: aws_bucket }); }); then on front end have following code:
this.$().fileupload({ datatype: 'json', type: 'post', autoupload: true, add: function (e, data) { $.ajax({ url: window.env.api_url+'/' + window.env.api_namespace + '/s3', type: 'post', datatype: 'json', data: { "filename": data.files[0].name }, async: false, success: function(retdata) { //do actual upload stuff now. data.url = 'https://'+retdata.bucket+'.s3.amazonaws.com/'; data.formdata = { key: retdata.key, awsaccesskeyid: retdata.aws_access, acl: 'private', policy: retdata.policy, signature: retdata.signature, success_action_status: 201, "content-type": retdata.contenttype }; data.submit() .success(function (result, textstatus, jqxhr) { console.log('success: ' + result); }) .error(function (jqxhr, textstatus, errorthrown) { console.log('error: ' + errorthrown); console.log(jqxhr); console.log('status: ' + textstatus); }); console.log(retdata); }, error: function (xhr, ajaxoptions, thrownerror) { console.log('ajax: ' + xhr); console.log('ajax: ' + thrownerror); } }); }, progressall: function (e, data) { var progress = parseint(data.loaded / data.total * 100, 10); $('#progress .progress-bar').css( 'width', progress + '%' ); } }); it seems though submitting correct form data match signature generation, getting following errors every time try submit:
signaturedoesnotmatch - request signature calculated not match signature provided. check key , signing method.
i struggling figure out might doing wrong, if can appreciate it.
i struggled while , got working using following:
in s3 handler:
var uploadtos3 = function(s3url, cb){ var fd = new formdata(); var file = document.getelementbyid('file').files[0]; var key = 'uploads\/' + file.name; fd.append('key', 'uploads\/' + file.name); fd.append('acl', 'public-read'); fd.append('content-type', 'multipart/form-data'); fd.append('awsaccesskeyid', 'xxxx'); fd.append('policy', s3url.s3policy); fd.append('signature', s3url.s3signature); fd.append('file', file); var xhr = new xmlhttprequest(); xhr.open('post', 'https://xxxx.s3.amazonaws.com', true); ///////////////////////////////////////////////////////// // keep track of upload progress can message// // user. // ///////////////////////////////////////////////////////// var firstprogressevent = true; xhr.loaded = 0; xhr.upload.addeventlistener('progress', function(e) { if (firstprogressevent) { firstprogressevent = false; } xhr.loaded += (e.loaded - xhr.loaded); $('progress').val((xhr.loaded / e.total) * 100); }, false); xhr.onreadystatechange = function(){ if ( xhr.readystate == 4 ) { if ( xhr.status >= 200 && xhr.status < 400 ) { cb(xhr.status); } else { cb(xhr.status); } } }; xhr.onerror = function () { error(xhr, xhr.status); }; xhr.send(fd); }; });
on server:
creates3policy = function(key, callback) { var date = new date(); var s3policy = { "expiration": new date(date.now() + 300000), "conditions": [ {"bucket": "xxx"}, ["starts-with", "$key", key], {"acl": "public-read"}, ["starts-with", "$content-type", "multipart/form-data"], ["content-length-range", 0, 524288000] ] }; //////////////////////////////////// // stringify , encode policy// //////////////////////////////////// var stringpolicy = json.stringify(s3policy); var base64policy = buffer(stringpolicy, "utf8").tostring("base64"); //////////////////////////////////// // sign base64 encoded policy // //////////////////////////////////// var signature = crypto.createhmac("sha1", process.env.aws_secret_access_key) .update(new buffer(base64policy, "utf8")).digest("base64"); //////////////////////////////////// // build results object // //////////////////////////////////// var s3credentials = { s3policy: base64policy, s3signature: signature }; callback(s3credentials); };
Comments
Post a Comment