@tmsfe/tms-core 0.0.139 → 0.0.141
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/encrypt.js +24 -13
- package/src/report/index.ts +1 -0
- package/src/request.js +52 -11
package/package.json
CHANGED
package/src/encrypt.js
CHANGED
|
@@ -13,11 +13,11 @@ import JSEncrypt from './jsencrypt.min.js';
|
|
|
13
13
|
const funAes = require('./aes.js');
|
|
14
14
|
// 加密模式
|
|
15
15
|
const ENCRYPT_MODE_ENUM = {
|
|
16
|
-
ASYMMETRIC_ENCRYPT_1: 1, // 非对称加密
|
|
17
|
-
NO_ENCRYPT_0: 0, // 不加密
|
|
18
|
-
ENCRYPT_COMPRESS: 1, // 加密压缩
|
|
19
|
-
ENCRYPT_NOCOMPRESS_2: 2, // 加密不压缩
|
|
20
|
-
NOENCRYPT_NOCOMPRESS_0: 0, // 不加密不压缩
|
|
16
|
+
ASYMMETRIC_ENCRYPT_1: '1', // 非对称加密
|
|
17
|
+
NO_ENCRYPT_0: '0', // 不加密
|
|
18
|
+
ENCRYPT_COMPRESS: '1', // 加密压缩
|
|
19
|
+
ENCRYPT_NOCOMPRESS_2: '2', // 加密不压缩
|
|
20
|
+
NOENCRYPT_NOCOMPRESS_0: '0', // 不加密不压缩
|
|
21
21
|
};
|
|
22
22
|
// -----------------------------------------------工具函数定义开始-----------------------------------------------------
|
|
23
23
|
// -----------------------------------------------------------------------------------------------------------------
|
|
@@ -66,6 +66,7 @@ const _getPrivateKeyInfo = (enforceUpdate) => {
|
|
|
66
66
|
privateKeyInfo = {
|
|
67
67
|
aesKey,
|
|
68
68
|
encryptAesKey,
|
|
69
|
+
publicKeyId: _getEccPublicId(),
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
return privateKeyInfo;
|
|
@@ -129,41 +130,46 @@ const _aesDecrypt = (cipherText, aesKey) => {
|
|
|
129
130
|
*/
|
|
130
131
|
const reqEncrypt = (method, params = {}, header = {}, encryptedResponseHeaderName = '') => {
|
|
131
132
|
let finalData = params;
|
|
133
|
+
const { aesKey, encryptAesKey, publicKeyId } = _getPrivateKeyInfo();
|
|
132
134
|
// 1. 处理请求参数
|
|
133
135
|
if (method.toUpperCase() === 'GET') {
|
|
134
136
|
const searchParams = Object.keys(params)
|
|
135
137
|
.map(key => `${encodeURIComponent(key)}=${encodeURIComponent(params[key])}`)
|
|
136
138
|
.join('&');
|
|
137
|
-
const encodedParams = _aesEncrypt(searchParams,
|
|
139
|
+
const encodedParams = _aesEncrypt(searchParams, aesKey);
|
|
138
140
|
finalData = { tmsec: encodedParams };
|
|
139
141
|
} else {
|
|
140
|
-
finalData = _aesEncrypt(JSON.stringify(params),
|
|
142
|
+
finalData = _aesEncrypt(JSON.stringify(params), aesKey);
|
|
141
143
|
}
|
|
142
144
|
// 2. 处理Headers
|
|
143
|
-
const encodedHeaders = _aesEncrypt(JSON.stringify(header),
|
|
145
|
+
const encodedHeaders = _aesEncrypt(JSON.stringify(header), aesKey);
|
|
144
146
|
return {
|
|
145
147
|
header: {
|
|
146
148
|
'X-Encrypt-Mode': ENCRYPT_MODE_ENUM.ASYMMETRIC_ENCRYPT_1,
|
|
147
149
|
'X-Compress-Mode': 'none',
|
|
148
150
|
'X-Encrypted-Headers': encodedHeaders,
|
|
149
|
-
'X-Encrypt-Pub':
|
|
150
|
-
'X-Encrypt-Key':
|
|
151
|
+
'X-Encrypt-Pub': publicKeyId,
|
|
152
|
+
'X-Encrypt-Key': encryptAesKey,
|
|
151
153
|
'X-Encrypt-Response': ENCRYPT_MODE_ENUM.ENCRYPT_NOCOMPRESS_2,
|
|
152
154
|
'X-Response-Header-Name': encryptedResponseHeaderName,
|
|
153
155
|
},
|
|
154
156
|
data: finalData,
|
|
155
|
-
aesKey
|
|
157
|
+
aesKey,
|
|
156
158
|
};
|
|
157
159
|
};
|
|
158
160
|
|
|
159
161
|
// 解密请求结果
|
|
160
162
|
const resDecrypt = (aesKey, header, data) => {
|
|
163
|
+
const formatHeader = {};
|
|
164
|
+
Object.keys(header).forEach((key) => {
|
|
165
|
+
formatHeader[key.toLocaleLowerCase()] = header[key];
|
|
166
|
+
});
|
|
161
167
|
const {
|
|
162
168
|
// 'x-encrypt-key': encryptKey, // 使用ECC公钥加密后的AES秘钥
|
|
163
169
|
'x-encrypt-response': encryptResponse, // 期望的响应加密模式1: 加密、压缩 2: 加密、不压缩
|
|
164
170
|
'x-response-headfer-name': encryptedResponseHeaderName, // 需要加密的响应Header: X-Header1,X-Header2
|
|
165
171
|
'x-encrypted-headers': encryptedHeaders, // 加密后的Header信息
|
|
166
|
-
} =
|
|
172
|
+
} = formatHeader;
|
|
167
173
|
if (!encryptResponse || encryptResponse === ENCRYPT_MODE_ENUM.NOENCRYPT_NOCOMPRESS_0) {
|
|
168
174
|
// 不需要解密,直接返回
|
|
169
175
|
return {
|
|
@@ -201,7 +207,12 @@ const resDecrypt = (aesKey, header, data) => {
|
|
|
201
207
|
* 更新秘钥信息:更新公钥,同时生成新的私钥
|
|
202
208
|
* @param {String: publicKey, Number: expireDate, String: id } param0
|
|
203
209
|
*/
|
|
204
|
-
const updateDecryptKey = (
|
|
210
|
+
const updateDecryptKey = (publicKeyInfo) => {
|
|
211
|
+
if (!publicKeyInfo) {
|
|
212
|
+
wx.$_publicKey = null;
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
const { publicKey, expireDate, id } = publicKeyInfo;
|
|
205
216
|
// 1. 存储新的公钥
|
|
206
217
|
wx.$_publicKey = {
|
|
207
218
|
publicKey,
|
package/src/report/index.ts
CHANGED
package/src/request.js
CHANGED
|
@@ -347,11 +347,17 @@ export default class Request {
|
|
|
347
347
|
}
|
|
348
348
|
|
|
349
349
|
// wx请求封装成promise
|
|
350
|
-
async wxRequest(path, method, header, data) {
|
|
350
|
+
async wxRequest(path, method, header = {}, data, needReport = false) {
|
|
351
|
+
if (needReport && path.indexOf('basic/event/upload') < 0) {
|
|
352
|
+
reporter.reportPerformance(
|
|
353
|
+
'request_encrypt_log', 'main', 'send_unencrypt_request', data.seqId,
|
|
354
|
+
!!wx.$_publicKey, Request.requestEncryptOpen, path,
|
|
355
|
+
);
|
|
356
|
+
}
|
|
351
357
|
return new Promise((resolve, reject) => {
|
|
352
358
|
wx.request({
|
|
353
359
|
url: path,
|
|
354
|
-
header,
|
|
360
|
+
header: { ...header, 'X-Trace-Id': data.seqId },
|
|
355
361
|
method,
|
|
356
362
|
data,
|
|
357
363
|
enableHttp2: true,
|
|
@@ -366,8 +372,13 @@ export default class Request {
|
|
|
366
372
|
}
|
|
367
373
|
|
|
368
374
|
async refreshEncryptKey() {
|
|
369
|
-
|
|
370
|
-
|
|
375
|
+
try {
|
|
376
|
+
const res = await this.doRequest('/basic/crypto/lastkey', {}, 'GET', {});
|
|
377
|
+
encryptObj.updateDecryptKey(res.data.resData);
|
|
378
|
+
} catch (e) {
|
|
379
|
+
encryptObj.updateDecryptKey(null);
|
|
380
|
+
reporter.reportPerformance('request_encrypt_log', 'main', 'refresh_encrypt_key_false', e);
|
|
381
|
+
}
|
|
371
382
|
}
|
|
372
383
|
|
|
373
384
|
// 如果全局请求加密开关关闭 || 当前请求内容不满足加密规则(publickey不为空且走sinan网关且非性能上报埋点)
|
|
@@ -378,6 +389,27 @@ export default class Request {
|
|
|
378
389
|
return true;
|
|
379
390
|
}
|
|
380
391
|
|
|
392
|
+
async dealEncryptionSwitch(resHeader) {
|
|
393
|
+
if (!resHeader || this.dealEncryptionSwitching) {
|
|
394
|
+
return false;
|
|
395
|
+
}
|
|
396
|
+
this.dealEncryptionSwitching = true;
|
|
397
|
+
const formatHeader = {};
|
|
398
|
+
Object.keys(resHeader).forEach(key => formatHeader[key.toLowerCase()] = resHeader[key]);
|
|
399
|
+
const encryptionAvaliable = formatHeader['x-encryption-available'] === '0';
|
|
400
|
+
if (encryptionAvaliable) {
|
|
401
|
+
// 关闭接下来请求的加密开关
|
|
402
|
+
wx.$_publicKey = null;
|
|
403
|
+
return false;
|
|
404
|
+
}
|
|
405
|
+
// 打开开关,如果当前是关闭状态,则需要刷新加密key
|
|
406
|
+
if (!wx.$_publicKey) {
|
|
407
|
+
await this.refreshEncryptKey();
|
|
408
|
+
}
|
|
409
|
+
this.dealEncryptionSwitching = false;
|
|
410
|
+
return true;
|
|
411
|
+
}
|
|
412
|
+
|
|
381
413
|
/**
|
|
382
414
|
* 创建发送请求任务
|
|
383
415
|
* @memberof Request
|
|
@@ -428,7 +460,7 @@ export default class Request {
|
|
|
428
460
|
};
|
|
429
461
|
// 当前请求不加密 || 不满足加密前提
|
|
430
462
|
if (!doEncrypt || !this.checkIfNeedEncrypt(finalUrl, data)) {
|
|
431
|
-
return this.wxRequest(finalUrl, method, header, data)
|
|
463
|
+
return this.wxRequest(finalUrl, method, header, data, true)
|
|
432
464
|
.then((res) => {
|
|
433
465
|
printLog(true, res.data);
|
|
434
466
|
return res;
|
|
@@ -456,18 +488,25 @@ export default class Request {
|
|
|
456
488
|
reporter.reportPerformance('request_encrypt_log', 'main', 'decrypt_response_success', data.seqId);
|
|
457
489
|
// 4. 处理解密失败的响应
|
|
458
490
|
switch (decryptData.errCode) {
|
|
459
|
-
case 11:
|
|
460
|
-
case 12:
|
|
461
|
-
case 13: // aes秘钥无效
|
|
462
|
-
|
|
491
|
+
case 11: // 公钥id失效
|
|
492
|
+
case 12: // 公钥已过期
|
|
493
|
+
case 13: { // aes秘钥无效
|
|
494
|
+
reporter.reportPerformance(
|
|
495
|
+
'request_encrypt_log', 'main', 'remote_response_decrypt_fail',
|
|
496
|
+
data.seqId, decryptData.errCode, retryTimes,
|
|
497
|
+
);
|
|
498
|
+
if (retryTimes > 2) {
|
|
463
499
|
throw new Error('解密失败,请重试');
|
|
464
500
|
}
|
|
465
|
-
reporter.reportPerformance('request_encrypt_log', 'main', 'remote_response_decrypt_fail', data.seqId, decryptData.errCode);
|
|
466
501
|
await this.refreshEncryptKey();
|
|
467
502
|
return this.createRequestTask(path, param, method, header, true, retryTimes + 1);
|
|
503
|
+
}
|
|
468
504
|
case 14: // 解密失败
|
|
469
505
|
// 请求不加密重试
|
|
470
|
-
reporter.reportPerformance(
|
|
506
|
+
reporter.reportPerformance(
|
|
507
|
+
'request_encrypt_log', 'main', 'remote_response_decrypt_fail',
|
|
508
|
+
data.seqId, decryptData.errCode, retryTimes,
|
|
509
|
+
);
|
|
471
510
|
return this.createRequestTask(path, param, method, header, false);
|
|
472
511
|
default:
|
|
473
512
|
break;
|
|
@@ -475,6 +514,8 @@ export default class Request {
|
|
|
475
514
|
result.header = decryptHeader;
|
|
476
515
|
result.data = decryptData;
|
|
477
516
|
printLog(true, result.data);
|
|
517
|
+
// 根据返回的响应头来控制接下来运行时的加密开关
|
|
518
|
+
this.dealEncryptionSwitch(resHeader);
|
|
478
519
|
return result;
|
|
479
520
|
} catch (err) {
|
|
480
521
|
printLog(false, err);
|