hexo/node_modules/ali-oss/lib/common/signUtils.js

182 lines
5.4 KiB
JavaScript

const crypto = require('crypto');
const is = require('is-type-of');
const { lowercaseKeyHeader } = require('./utils/lowercaseKeyHeader');
/**
*
* @param {String} resourcePath
* @param {Object} parameters
* @return
*/
exports.buildCanonicalizedResource = function buildCanonicalizedResource(resourcePath, parameters) {
let canonicalizedResource = `${resourcePath}`;
let separatorString = '?';
if (is.string(parameters) && parameters.trim() !== '') {
canonicalizedResource += separatorString + parameters;
} else if (is.array(parameters)) {
parameters.sort();
canonicalizedResource += separatorString + parameters.join('&');
} else if (parameters) {
const compareFunc = (entry1, entry2) => {
if (entry1[0] > entry2[0]) {
return 1;
} else if (entry1[0] < entry2[0]) {
return -1;
}
return 0;
};
const processFunc = key => {
canonicalizedResource += separatorString + key;
if (parameters[key] || parameters[key] === 0) {
canonicalizedResource += `=${parameters[key]}`;
}
separatorString = '&';
};
Object.keys(parameters).sort(compareFunc).forEach(processFunc);
}
return canonicalizedResource;
};
/**
* @param {String} method
* @param {String} resourcePath
* @param {Object} request
* @param {String} expires
* @return {String} canonicalString
*/
exports.buildCanonicalString = function canonicalString(method, resourcePath, request, expires) {
request = request || {};
const headers = lowercaseKeyHeader(request.headers);
const OSS_PREFIX = 'x-oss-';
const ossHeaders = [];
const headersToSign = {};
let signContent = [
method.toUpperCase(),
headers['content-md5'] || '',
headers['content-type'],
expires || headers['x-oss-date']
];
Object.keys(headers).forEach(key => {
const lowerKey = key.toLowerCase();
if (lowerKey.indexOf(OSS_PREFIX) === 0) {
headersToSign[lowerKey] = String(headers[key]).trim();
}
});
Object.keys(headersToSign)
.sort()
.forEach(key => {
ossHeaders.push(`${key}:${headersToSign[key]}`);
});
signContent = signContent.concat(ossHeaders);
signContent.push(this.buildCanonicalizedResource(resourcePath, request.parameters));
return signContent.join('\n');
};
/**
* @param {String} accessKeySecret
* @param {String} canonicalString
*/
exports.computeSignature = function computeSignature(accessKeySecret, canonicalString, headerEncoding = 'utf-8') {
const signature = crypto.createHmac('sha1', accessKeySecret);
return signature.update(Buffer.from(canonicalString, headerEncoding)).digest('base64');
};
/**
* @param {String} accessKeyId
* @param {String} accessKeySecret
* @param {String} canonicalString
*/
exports.authorization = function authorization(accessKeyId, accessKeySecret, canonicalString, headerEncoding) {
return `OSS ${accessKeyId}:${this.computeSignature(accessKeySecret, canonicalString, headerEncoding)}`;
};
/**
*
* @param {String} accessKeySecret
* @param {Object} options
* @param {String} resource
* @param {Number} expires
*/
exports._signatureForURL = function _signatureForURL(accessKeySecret, options = {}, resource, expires, headerEncoding) {
const headers = {};
const { subResource = {} } = options;
if (options.process) {
const processKeyword = 'x-oss-process';
subResource[processKeyword] = options.process;
}
if (options.trafficLimit) {
const trafficLimitKey = 'x-oss-traffic-limit';
subResource[trafficLimitKey] = options.trafficLimit;
}
if (options.response) {
Object.keys(options.response).forEach(k => {
const key = `response-${k.toLowerCase()}`;
subResource[key] = options.response[k];
});
}
Object.keys(options).forEach(key => {
const lowerKey = key.toLowerCase();
const value = options[key];
if (lowerKey.indexOf('x-oss-') === 0) {
headers[lowerKey] = value;
} else if (lowerKey.indexOf('content-md5') === 0) {
headers[key] = value;
} else if (lowerKey.indexOf('content-type') === 0) {
headers[key] = value;
}
});
if (Object.prototype.hasOwnProperty.call(options, 'security-token')) {
subResource['security-token'] = options['security-token'];
}
if (Object.prototype.hasOwnProperty.call(options, 'callback')) {
const json = {
callbackUrl: encodeURI(options.callback.url),
callbackBody: options.callback.body
};
if (options.callback.host) {
json.callbackHost = options.callback.host;
}
if (options.callback.contentType) {
json.callbackBodyType = options.callback.contentType;
}
subResource.callback = Buffer.from(JSON.stringify(json)).toString('base64');
if (options.callback.customValue) {
const callbackVar = {};
Object.keys(options.callback.customValue).forEach(key => {
callbackVar[`x:${key}`] = options.callback.customValue[key];
});
subResource['callback-var'] = Buffer.from(JSON.stringify(callbackVar)).toString('base64');
}
}
const canonicalString = this.buildCanonicalString(
options.method,
resource,
{
headers,
parameters: subResource
},
expires.toString()
);
return {
Signature: this.computeSignature(accessKeySecret, canonicalString, headerEncoding),
subResource
};
};