forked from lunanting/cangku
54 lines
1.6 KiB
JavaScript
54 lines
1.6 KiB
JavaScript
'use strict';
|
|
|
|
const test = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
const {
|
|
buildCanonicalRequest,
|
|
isRequestIpAllowed,
|
|
signCanonicalRequest,
|
|
verifyHmacRequest,
|
|
} = require('../src/services/selectionFissionExternalSecurity');
|
|
|
|
function createRequest(headers = {}, overrides = {}) {
|
|
return {
|
|
method: 'POST',
|
|
originalUrl: '/api/external/selection-fission/tasks/claim',
|
|
rawBody: '{"dingtalkUserName":"张三"}',
|
|
headers,
|
|
get(name) {
|
|
return headers[String(name).toLowerCase()] || '';
|
|
},
|
|
...overrides,
|
|
};
|
|
}
|
|
|
|
test('external API HMAC verifies canonical request and rejects replay', () => {
|
|
const timestamp = '1784779200';
|
|
const nonce = 'nonce_12345678';
|
|
const apiKey = 'sf_live_test_1234567890';
|
|
const request = createRequest();
|
|
const canonical = buildCanonicalRequest({
|
|
timestamp,
|
|
nonce,
|
|
method: request.method,
|
|
originalUrl: request.originalUrl,
|
|
rawBody: request.rawBody,
|
|
});
|
|
request.headers['x-timestamp'] = timestamp;
|
|
request.headers['x-nonce'] = nonce;
|
|
request.headers['x-signature'] = signCanonicalRequest(apiKey, canonical);
|
|
|
|
const nowMs = Number(timestamp) * 1000;
|
|
assert.equal(verifyHmacRequest(request, apiKey, 99, { nowMs }).valid, true);
|
|
assert.match(
|
|
verifyHmacRequest(request, apiKey, 99, { nowMs }).reason,
|
|
/已使用/
|
|
);
|
|
});
|
|
|
|
test('external API IP whitelist compares normalized exact addresses', () => {
|
|
assert.equal(isRequestIpAllowed('::ffff:127.0.0.1', ['127.0.0.1']), true);
|
|
assert.equal(isRequestIpAllowed('203.0.113.11', ['203.0.113.10']), false);
|
|
assert.equal(isRequestIpAllowed('203.0.113.11', []), true);
|
|
});
|