mirror of
https://github.com/certd/certd.git
synced 2026-05-16 13:17:29 +08:00
chore:
This commit is contained in:
@@ -0,0 +1,13 @@
|
||||
module.exports = class RequestSigner {
|
||||
constructor (request) {
|
||||
this.request = request
|
||||
}
|
||||
|
||||
setServiceClientId (id) {
|
||||
this.serviceClientId = id
|
||||
}
|
||||
|
||||
getServiceClientId () {
|
||||
return this.serviceClientId
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
// Copyright 2018 JDCLOUD.COM
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
// This signer is modified from AWS V4 signer algorithm.
|
||||
|
||||
var util = require("../util");
|
||||
var RequestSigner = require("./request_signer");
|
||||
var v2Credentials = require("./v2_credentials");
|
||||
var uuid = require("uuid");
|
||||
var JDCloud = require("../core");
|
||||
|
||||
module.exports = class SignerV2 extends RequestSigner {
|
||||
constructor(request, serviceName, options = {}) {
|
||||
super(request);
|
||||
this.signatureCache = true;
|
||||
this.algorithm = "JDCLOUD2-HMAC-SHA256";
|
||||
this.unsignableHeaders = ["authorization", "user-agent"];
|
||||
this.serviceName = serviceName;
|
||||
// this.signatureCache = typeof options.signatureCache === 'boolean' ? options.signatureCache : true;
|
||||
}
|
||||
|
||||
// 签名流程见 https://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-header-based-auth.html
|
||||
|
||||
addAuthorization(credentials, date) {
|
||||
// var datetime = '20180119T070300Z';
|
||||
var datetime = util.date.iso8601(date).replace(/[:-]|\.\d{3}/g, "");
|
||||
this.addHeaders(credentials, datetime);
|
||||
this.request.request.headers.set("Authorization", this.authorization(credentials, datetime));
|
||||
}
|
||||
|
||||
addHeaders(credentials, datetime) {
|
||||
this.request.request.headers.set("x-jdcloud-date", datetime);
|
||||
this.request.request.headers.set("x-jdcloud-nonce", uuid.v4());
|
||||
this.request.request.headers.set("host", this.request.service.config.endpoint.host);
|
||||
}
|
||||
|
||||
signedHeaders() {
|
||||
var keys = [];
|
||||
this.request.request.headers.forEach((value, key) => {
|
||||
key = key.toLowerCase();
|
||||
if (this.isSignableHeader(key)) {
|
||||
keys.push(key);
|
||||
}
|
||||
});
|
||||
/* util.each.call(this, this.request.headers, function (key) {
|
||||
|
||||
}); */
|
||||
return keys.sort().join(";");
|
||||
}
|
||||
|
||||
credentialString(datetime) {
|
||||
return v2Credentials.createScope(datetime.substr(0, 8), this.request.regionId, this.serviceName);
|
||||
}
|
||||
|
||||
signature(credentials, datetime) {
|
||||
var signingKey = v2Credentials.getSigningKey(credentials, datetime.substr(0, 8), this.request.regionId, this.serviceName, this.signatureCache);
|
||||
return util.crypto.hmac(signingKey, this.stringToSign(datetime), "hex");
|
||||
}
|
||||
|
||||
stringToSign(datetime) {
|
||||
var parts = [];
|
||||
parts.push(this.algorithm);
|
||||
parts.push(datetime);
|
||||
parts.push(this.credentialString(datetime));
|
||||
parts.push(this.hexEncodedHash(this.canonicalString()));
|
||||
JDCloud.config.logger("StringToSign is \n" + JSON.stringify(parts), "DEBUG");
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
// 构建标准签名字符串
|
||||
canonicalString() {
|
||||
var parts = [];
|
||||
var pathname = this.request.path;
|
||||
// if (this.serviceName !== 'jfs') {
|
||||
// pathname = util.uriEscapePath(pathname)
|
||||
// }
|
||||
|
||||
parts.push(this.request.request.method);
|
||||
parts.push(pathname);
|
||||
parts.push(this.request.search());
|
||||
parts.push(this.canonicalHeaders() + "\n");
|
||||
parts.push(this.signedHeaders());
|
||||
parts.push(this.hexEncodedBodyHash());
|
||||
JDCloud.config.logger("canonicalString is \n" + JSON.stringify(parts), "DEBUG");
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
canonicalHeaders() {
|
||||
var headers = [];
|
||||
this.request.request.headers.forEach((value, key) => {
|
||||
headers.push([key, value]);
|
||||
});
|
||||
headers.sort(function (a, b) {
|
||||
return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : 1;
|
||||
});
|
||||
var parts = [];
|
||||
util.arrayEach.call(this, headers, function (item) {
|
||||
var key = item[0].toLowerCase();
|
||||
if (this.isSignableHeader(key)) {
|
||||
var value = item[1];
|
||||
if (typeof value === "undefined" || value === null || typeof value.toString !== "function") {
|
||||
throw util.error(new Error("Header " + key + " contains invalid value"), {
|
||||
code: "InvalidHeader",
|
||||
});
|
||||
}
|
||||
parts.push(key + ":" + this.canonicalHeaderValues(value.toString()));
|
||||
}
|
||||
});
|
||||
return parts.join("\n");
|
||||
}
|
||||
|
||||
canonicalHeaderValues(values) {
|
||||
return values.replace(/\s+/g, " ").replace(/^\s+|\s+$/g, "");
|
||||
}
|
||||
|
||||
authorization(credentials, datetime) {
|
||||
var parts = [];
|
||||
var credString = this.credentialString(datetime);
|
||||
parts.push(this.algorithm + " Credential=" + credentials.accessKeyId + "/" + credString);
|
||||
parts.push("SignedHeaders=" + this.signedHeaders());
|
||||
parts.push("Signature=" + this.signature(credentials, datetime));
|
||||
JDCloud.config.logger("Signature is \n" + JSON.stringify(parts), "DEBUG");
|
||||
return parts.join(", ");
|
||||
}
|
||||
|
||||
hexEncodedHash(string) {
|
||||
return util.crypto.sha256(string, "hex");
|
||||
}
|
||||
|
||||
hexEncodedBodyHash() {
|
||||
return this.hexEncodedHash(this.request.request.body || "");
|
||||
/* var request = this.request;
|
||||
if (this.isPresigned() && this.serviceName === 's3' && !request.body) {
|
||||
return 'UNSIGNED-PAYLOAD';
|
||||
} else if (request.headers['X-Amz-Content-Sha256']) {
|
||||
return request.headers['X-Amz-Content-Sha256'];
|
||||
} else {
|
||||
return this.hexEncodedHash(this.request.body || '');
|
||||
} */
|
||||
}
|
||||
|
||||
isSignableHeader(key) {
|
||||
if (key.toLowerCase().includes("x-jdcloud-")) {
|
||||
return true;
|
||||
}
|
||||
return !this.unsignableHeaders.includes(key.toLowerCase());
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,80 @@
|
||||
var cachedSecret = {}
|
||||
var cacheQueue = []
|
||||
var maxCacheEntries = 50
|
||||
var v2Identifier = 'jdcloud2_request'
|
||||
|
||||
var util = require('../util')
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* @api private
|
||||
*
|
||||
* @param date [String]
|
||||
* @param region [String]
|
||||
* @param serviceName [String]
|
||||
* @return [String]
|
||||
*/
|
||||
createScope: function createScope (date, region, serviceName) {
|
||||
return [date.substr(0, 8), region, serviceName, v2Identifier].join('/')
|
||||
},
|
||||
|
||||
/**
|
||||
* @api private
|
||||
*
|
||||
* @param credentials [Credentials]
|
||||
* @param date [String]
|
||||
* @param region [String]
|
||||
* @param service [String]
|
||||
* @param shouldCache [Boolean]
|
||||
* @return [String]
|
||||
*/
|
||||
getSigningKey: function getSigningKey (
|
||||
credentials,
|
||||
date,
|
||||
region,
|
||||
service,
|
||||
shouldCache
|
||||
) {
|
||||
var credsIdentifier = util.crypto.hmac(
|
||||
credentials.secretAccessKey,
|
||||
credentials.accessKeyId,
|
||||
'base64'
|
||||
)
|
||||
var cacheKey = [credsIdentifier, date, region, service].join('_')
|
||||
shouldCache = shouldCache !== false
|
||||
if (shouldCache && cacheKey in cachedSecret) {
|
||||
return cachedSecret[cacheKey]
|
||||
}
|
||||
|
||||
var kDate = util.crypto.hmac(
|
||||
'JDCLOUD2' + credentials.secretAccessKey,
|
||||
date,
|
||||
'buffer'
|
||||
)
|
||||
var kRegion = util.crypto.hmac(kDate, region, 'buffer')
|
||||
var kService = util.crypto.hmac(kRegion, service, 'buffer')
|
||||
|
||||
var signingKey = util.crypto.hmac(kService, v2Identifier, 'buffer')
|
||||
if (shouldCache) {
|
||||
cachedSecret[cacheKey] = signingKey
|
||||
cacheQueue.push(cacheKey)
|
||||
if (cacheQueue.length > maxCacheEntries) {
|
||||
// remove the oldest entry (not the least recently used)
|
||||
delete cachedSecret[cacheQueue.shift()]
|
||||
}
|
||||
}
|
||||
|
||||
return signingKey
|
||||
},
|
||||
|
||||
/**
|
||||
* @api private
|
||||
*
|
||||
* Empties the derived signing key cache. Made available for testing purposes
|
||||
* only.
|
||||
*/
|
||||
emptyCache: function emptyCache () {
|
||||
cachedSecret = {}
|
||||
cacheQueue = []
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user