Backend half
This commit is contained in:
+175
@@ -0,0 +1,175 @@
|
||||
var AWS = require('../core');
|
||||
var inherit = AWS.util.inherit;
|
||||
|
||||
/**
|
||||
* @api private
|
||||
*/
|
||||
AWS.Signers.S3 = inherit(AWS.Signers.RequestSigner, {
|
||||
/**
|
||||
* When building the stringToSign, these sub resource params should be
|
||||
* part of the canonical resource string with their NON-decoded values
|
||||
*/
|
||||
subResources: {
|
||||
'acl': 1,
|
||||
'accelerate': 1,
|
||||
'analytics': 1,
|
||||
'cors': 1,
|
||||
'lifecycle': 1,
|
||||
'delete': 1,
|
||||
'inventory': 1,
|
||||
'location': 1,
|
||||
'logging': 1,
|
||||
'metrics': 1,
|
||||
'notification': 1,
|
||||
'partNumber': 1,
|
||||
'policy': 1,
|
||||
'requestPayment': 1,
|
||||
'replication': 1,
|
||||
'restore': 1,
|
||||
'tagging': 1,
|
||||
'torrent': 1,
|
||||
'uploadId': 1,
|
||||
'uploads': 1,
|
||||
'versionId': 1,
|
||||
'versioning': 1,
|
||||
'versions': 1,
|
||||
'website': 1
|
||||
},
|
||||
|
||||
// when building the stringToSign, these querystring params should be
|
||||
// part of the canonical resource string with their NON-encoded values
|
||||
responseHeaders: {
|
||||
'response-content-type': 1,
|
||||
'response-content-language': 1,
|
||||
'response-expires': 1,
|
||||
'response-cache-control': 1,
|
||||
'response-content-disposition': 1,
|
||||
'response-content-encoding': 1
|
||||
},
|
||||
|
||||
addAuthorization: function addAuthorization(credentials, date) {
|
||||
if (!this.request.headers['presigned-expires']) {
|
||||
this.request.headers['X-Amz-Date'] = AWS.util.date.rfc822(date);
|
||||
}
|
||||
|
||||
if (credentials.sessionToken) {
|
||||
// presigned URLs require this header to be lowercased
|
||||
this.request.headers['x-amz-security-token'] = credentials.sessionToken;
|
||||
}
|
||||
|
||||
var signature = this.sign(credentials.secretAccessKey, this.stringToSign());
|
||||
var auth = 'AWS ' + credentials.accessKeyId + ':' + signature;
|
||||
|
||||
this.request.headers['Authorization'] = auth;
|
||||
},
|
||||
|
||||
stringToSign: function stringToSign() {
|
||||
var r = this.request;
|
||||
|
||||
var parts = [];
|
||||
parts.push(r.method);
|
||||
parts.push(r.headers['Content-MD5'] || '');
|
||||
parts.push(r.headers['Content-Type'] || '');
|
||||
|
||||
// This is the "Date" header, but we use X-Amz-Date.
|
||||
// The S3 signing mechanism requires us to pass an empty
|
||||
// string for this Date header regardless.
|
||||
parts.push(r.headers['presigned-expires'] || '');
|
||||
|
||||
var headers = this.canonicalizedAmzHeaders();
|
||||
if (headers) parts.push(headers);
|
||||
parts.push(this.canonicalizedResource());
|
||||
|
||||
return parts.join('\n');
|
||||
|
||||
},
|
||||
|
||||
canonicalizedAmzHeaders: function canonicalizedAmzHeaders() {
|
||||
|
||||
var amzHeaders = [];
|
||||
|
||||
AWS.util.each(this.request.headers, function (name) {
|
||||
if (name.match(/^x-amz-/i))
|
||||
amzHeaders.push(name);
|
||||
});
|
||||
|
||||
amzHeaders.sort(function (a, b) {
|
||||
return a.toLowerCase() < b.toLowerCase() ? -1 : 1;
|
||||
});
|
||||
|
||||
var parts = [];
|
||||
AWS.util.arrayEach.call(this, amzHeaders, function (name) {
|
||||
parts.push(name.toLowerCase() + ':' + String(this.request.headers[name]));
|
||||
});
|
||||
|
||||
return parts.join('\n');
|
||||
|
||||
},
|
||||
|
||||
canonicalizedResource: function canonicalizedResource() {
|
||||
|
||||
var r = this.request;
|
||||
|
||||
var parts = r.path.split('?');
|
||||
var path = parts[0];
|
||||
var querystring = parts[1];
|
||||
|
||||
var resource = '';
|
||||
|
||||
if (r.virtualHostedBucket)
|
||||
resource += '/' + r.virtualHostedBucket;
|
||||
|
||||
resource += path;
|
||||
|
||||
if (querystring) {
|
||||
|
||||
// collect a list of sub resources and query params that need to be signed
|
||||
var resources = [];
|
||||
|
||||
AWS.util.arrayEach.call(this, querystring.split('&'), function (param) {
|
||||
var name = param.split('=')[0];
|
||||
var value = param.split('=')[1];
|
||||
if (this.subResources[name] || this.responseHeaders[name]) {
|
||||
var subresource = { name: name };
|
||||
if (value !== undefined) {
|
||||
if (this.subResources[name]) {
|
||||
subresource.value = value;
|
||||
} else {
|
||||
subresource.value = decodeURIComponent(value);
|
||||
}
|
||||
}
|
||||
resources.push(subresource);
|
||||
}
|
||||
});
|
||||
|
||||
resources.sort(function (a, b) { return a.name < b.name ? -1 : 1; });
|
||||
|
||||
if (resources.length) {
|
||||
|
||||
querystring = [];
|
||||
AWS.util.arrayEach(resources, function (res) {
|
||||
if (res.value === undefined) {
|
||||
querystring.push(res.name);
|
||||
} else {
|
||||
querystring.push(res.name + '=' + res.value);
|
||||
}
|
||||
});
|
||||
|
||||
resource += '?' + querystring.join('&');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return resource;
|
||||
|
||||
},
|
||||
|
||||
sign: function sign(secret, string) {
|
||||
return AWS.util.crypto.hmac(secret, string, 'base64', 'sha1');
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* @api private
|
||||
*/
|
||||
module.exports = AWS.Signers.S3;
|
||||
Reference in New Issue
Block a user