@lingxiteam/ebe-utils 0.0.33 → 0.0.37
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/es/index.d.ts +5 -1
- package/es/index.js +107 -62
- package/lib/public/src/services/api/engine.ts +0 -2
- package/lib/public/src/utils/Security/clientCapabilities.ts +8 -0
- package/lib/public/src/utils/Security/config.ts +56 -49
- package/lib/public/src/utils/Security/const.ts +38 -127
- package/lib/public/src/utils/Security/debug/data.ts +86 -0
- package/lib/public/src/utils/Security/debug/index.ts +21 -0
- package/lib/public/src/utils/Security/encipher/sign.ts +25 -56
- package/lib/public/src/utils/Security/html.ts +52 -0
- package/lib/public/src/utils/Security/httpEncryption.ts +42 -23
- package/lib/public/src/utils/Security/index.ts +15 -7
- package/lib/public/src/utils/Security/requester/fetch.ts +87 -52
- package/lib/public/src/utils/Security/requester/wx.ts +60 -11
- package/lib/public/src/utils/Security/requester/xhr.ts +194 -40
- package/lib/public/src/utils/Security/types.ts +8 -90
- package/lib/public/src/utils/Security/urlEncryption.ts +108 -0
- package/lib/public/src/utils/Security/utils/atob.ts +34 -0
- package/lib/public/src/utils/Security/utils/caseInsensitive.ts +25 -0
- package/lib/public/src/utils/Security/utils/check.ts +27 -3
- package/lib/public/src/utils/Security/utils/cookie.ts +101 -53
- package/lib/public/src/utils/Security/utils/encrypted.ts +190 -43
- package/lib/public/src/utils/Security/utils/random.ts +21 -0
- package/lib/public/src/utils/Security/utils/storge.ts +22 -0
- package/lib/public/src/utils/Security/utils/url.ts +30 -5
- package/lib/public/src/utils/getSceneCode.ts +51 -0
- package/package.json +2 -2
|
@@ -1,129 +1,40 @@
|
|
|
1
1
|
// 不建议使用环境变量,后期通一通过config来配置
|
|
2
2
|
// 兼容非node环境构建(如:小程序)
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
'
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
'
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
'
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
'
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
'
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
'a',
|
|
42
|
-
'c',
|
|
43
|
-
'0',
|
|
44
|
-
'I',
|
|
45
|
-
'a',
|
|
46
|
-
].join('');
|
|
47
|
-
|
|
48
|
-
export const securityHeaderKey = 'XA-TYPE';
|
|
49
|
-
|
|
50
|
-
export const signSaltKey =
|
|
51
|
-
process.env.LING_XI_USER_KEY_IN_COOKIE || 'X-LX-N-ID';
|
|
52
|
-
|
|
53
|
-
export const signKey =
|
|
54
|
-
process.env.LING_XI_HTTP_SIGN_KEY ||
|
|
55
|
-
[
|
|
56
|
-
'z',
|
|
57
|
-
'r',
|
|
58
|
-
'T',
|
|
59
|
-
'5',
|
|
60
|
-
'b',
|
|
61
|
-
'i',
|
|
62
|
-
'2',
|
|
63
|
-
'e',
|
|
64
|
-
's',
|
|
65
|
-
'c',
|
|
66
|
-
'X',
|
|
67
|
-
'i',
|
|
68
|
-
'l',
|
|
69
|
-
'a',
|
|
70
|
-
'H',
|
|
71
|
-
'1',
|
|
72
|
-
'f',
|
|
73
|
-
's',
|
|
74
|
-
'6',
|
|
75
|
-
'5',
|
|
76
|
-
'3',
|
|
77
|
-
'u',
|
|
78
|
-
'Z',
|
|
79
|
-
'i',
|
|
80
|
-
'H',
|
|
81
|
-
'9',
|
|
82
|
-
'R',
|
|
83
|
-
'W',
|
|
84
|
-
'f',
|
|
85
|
-
'z',
|
|
86
|
-
'C',
|
|
87
|
-
'S',
|
|
88
|
-
].join('');
|
|
89
|
-
|
|
90
|
-
export const signHeaderKey =
|
|
91
|
-
process.env.LINGXI_HTTP_SIGN_HEADER_KEY ||
|
|
92
|
-
process.env.REACT_APP_HTTP_SIGN_HEADER_KEY ||
|
|
93
|
-
process.env.UMI_APP_HTTP_SIGN_HEADER_KEY ||
|
|
94
|
-
process.env.FISHX_APP_HTTP_SIGN_HEADER_KEY ||
|
|
95
|
-
defaultSignHeaderKey;
|
|
96
|
-
|
|
97
|
-
export const rsaPublicKey =
|
|
98
|
-
process.env.LINGXI_HTTP_RSA_PUBLIC_KEY ||
|
|
99
|
-
process.env.REACT_APP_HTTP_RSA_PUBLIC_KEY ||
|
|
100
|
-
process.env.UMI_APP_HTTP_RSA_PUBLIC_KEY ||
|
|
101
|
-
process.env.FISHX_APP_HTTP_RSA_PUBLIC_KEY;
|
|
102
|
-
|
|
103
|
-
export const rsaPrivKey =
|
|
104
|
-
process.env.LINGXI_HTTP_RSA_PRIV_KEY ||
|
|
105
|
-
process.env.REACT_APP_HTTP_RSA_PRIV_KEY ||
|
|
106
|
-
process.env.UMI_APP_HTTP_RSA_PRIV_KEY ||
|
|
107
|
-
process.env.FISHX_APP_HTTP_RSA_PRIV_KEY;
|
|
108
|
-
|
|
109
|
-
export const aesKey =
|
|
110
|
-
process.env.LINGXI_HTTP_AES_KEY ||
|
|
111
|
-
process.env.REACT_APP_HTTP_AES_KEY ||
|
|
112
|
-
process.env.UMI_APP_HTTP_AES_KEY ||
|
|
113
|
-
process.env.FISHX_APP_HTTP_AES_KEY ||
|
|
114
|
-
defaultAESKey;
|
|
115
|
-
|
|
116
|
-
export const desKey =
|
|
117
|
-
process.env.LINGXI_HTTP_DES_KEY ||
|
|
118
|
-
process.env.REACT_APP_HTTP_DES_KEY ||
|
|
119
|
-
process.env.UMI_APP_HTTP_DES_KEY ||
|
|
120
|
-
process.env.FISHX_APP_HTTP_DES_KEY ||
|
|
121
|
-
defaultDESKey;
|
|
122
|
-
|
|
123
|
-
export default {
|
|
124
|
-
signKey,
|
|
125
|
-
rsaPublicKey,
|
|
126
|
-
rsaPrivKey,
|
|
127
|
-
aesKey,
|
|
128
|
-
desKey,
|
|
129
|
-
};
|
|
3
|
+
// const _process = typeof process === 'undefined' ? { env: {} } as any : process;
|
|
4
|
+
import customAtob from './utils/atob';
|
|
5
|
+
|
|
6
|
+
export const reqIdKey = 'reqid';
|
|
7
|
+
|
|
8
|
+
export const commonGlobal: any = (function () {
|
|
9
|
+
// nodejs、wx、electron 环境(在wx和electron同时具备global和window,wx下写入的全局变量在global里,故优先使用global)
|
|
10
|
+
if (typeof global !== 'undefined') {
|
|
11
|
+
return global;
|
|
12
|
+
}
|
|
13
|
+
// 使用标准的方式来获取不同环境下的全局 this 对象
|
|
14
|
+
if (typeof globalThis !== 'undefined') {
|
|
15
|
+
return globalThis;
|
|
16
|
+
}
|
|
17
|
+
// 浏览器环境
|
|
18
|
+
if (typeof window !== 'undefined') {
|
|
19
|
+
return window;
|
|
20
|
+
}
|
|
21
|
+
// Workers环境
|
|
22
|
+
if (typeof self !== 'undefined') {
|
|
23
|
+
return self;
|
|
24
|
+
}
|
|
25
|
+
return {};
|
|
26
|
+
})();
|
|
27
|
+
|
|
28
|
+
// 'd86d7bab3d6ac01a,X-SIGN,d86d7bab3d6ac0Ia,XA-TYPE,X-LX-N-ID,zrT5bi2escXilaH1fs653uZiH9RWfzCS'
|
|
29
|
+
const k = customAtob(
|
|
30
|
+
'ZDg2ZDdiYWIzZDZhYzAxYSxYLVNJR04sZDg2ZDdiYWIzZDZhYzBJYSxYQS1UWVBFLFgtTFgtTi1JRCx6clQ1YmkyZXNjWGlsYUgxZnM2NTN1WmlIOVJXZnpDUw==',
|
|
31
|
+
).split(',');
|
|
32
|
+
|
|
33
|
+
export const aesKey = k[0];
|
|
34
|
+
export const signHeaderKey = k[1];
|
|
35
|
+
export const lxKey = k[2];
|
|
36
|
+
export const securityHeaderKey = k[3];
|
|
37
|
+
export const signSaltKey = k[4];
|
|
38
|
+
export const signKey = k[5];
|
|
39
|
+
export const rsaPublicKey = k[6];
|
|
40
|
+
export const rsaPrivKey = k[7];
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { commonGlobal } from '../const';
|
|
2
|
+
import message from '../utils/message';
|
|
3
|
+
import generateRandomNumber from '../utils/random';
|
|
4
|
+
|
|
5
|
+
export type configTpe = {
|
|
6
|
+
globalAccess?: boolean;
|
|
7
|
+
storeMax?: number;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* 存储每个请求的签名/加密数据
|
|
12
|
+
* 目前仅支持通过localStorage来开启数据记录,避免误将setConfig设置的debug发到生产环境
|
|
13
|
+
* 通过拷贝请求头里获取 reqid,在控制台粘贴该信息进行查看调试数据
|
|
14
|
+
*/
|
|
15
|
+
class DebugDataStore {
|
|
16
|
+
private tag: string = '';
|
|
17
|
+
|
|
18
|
+
private config: configTpe = {};
|
|
19
|
+
|
|
20
|
+
private data: Record<string, any> = {};
|
|
21
|
+
|
|
22
|
+
private storeAllKeys: string[] = [];
|
|
23
|
+
|
|
24
|
+
private storeActiveKeys: string[] = [];
|
|
25
|
+
|
|
26
|
+
constructor(config: configTpe = {}) {
|
|
27
|
+
this.config = Object.assign(
|
|
28
|
+
{
|
|
29
|
+
globalAccess: true,
|
|
30
|
+
storeMax: 20,
|
|
31
|
+
},
|
|
32
|
+
config,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
this.tag = `LXREQ${generateRandomNumber(2)}`;
|
|
36
|
+
|
|
37
|
+
const _this = this;
|
|
38
|
+
|
|
39
|
+
if (this.config.globalAccess) {
|
|
40
|
+
commonGlobal[this.tag] = new Proxy(this.data, {
|
|
41
|
+
get(target, props) {
|
|
42
|
+
if (typeof props === 'string') {
|
|
43
|
+
if (props === 'toJSON') {
|
|
44
|
+
return '{}';
|
|
45
|
+
}
|
|
46
|
+
return _this.getData(`${_this.tag}.${props}`);
|
|
47
|
+
}
|
|
48
|
+
return {};
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public createId() {
|
|
55
|
+
return `${this.tag}.T${generateRandomNumber(2)}${Date.now()}`;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public store(id: string, key: string, value: any) {
|
|
59
|
+
const _id = id.replace(/(window|global|self|globalThis)\./g, '');
|
|
60
|
+
if (!this.storeAllKeys.includes(_id)) {
|
|
61
|
+
this.data[_id] = { [key]: value };
|
|
62
|
+
this.storeAllKeys.push(_id);
|
|
63
|
+
this.storeActiveKeys.push(_id);
|
|
64
|
+
if (
|
|
65
|
+
this.config.storeMax &&
|
|
66
|
+
this.storeActiveKeys.length > this.config.storeMax
|
|
67
|
+
) {
|
|
68
|
+
const delkey = this.storeActiveKeys.shift();
|
|
69
|
+
if (delkey) {
|
|
70
|
+
delete this.data[delkey];
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} else {
|
|
74
|
+
this.data[_id] = Object.assign(this.data[_id], { [key]: value });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public getData(id: string) {
|
|
79
|
+
if (this.storeAllKeys.includes(id) && !this.storeActiveKeys.includes(id)) {
|
|
80
|
+
message.warn('数据已失效');
|
|
81
|
+
}
|
|
82
|
+
return this.data[id];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export default DebugDataStore;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import storageUtil from '../utils/storge';
|
|
2
|
+
import type { configTpe } from './data';
|
|
3
|
+
import DebugDataStore from './data';
|
|
4
|
+
|
|
5
|
+
// 通过本地存储的参数开启调试
|
|
6
|
+
export const isAvailable = !!storageUtil.get('lxDebug');
|
|
7
|
+
|
|
8
|
+
const debug = (() => {
|
|
9
|
+
if (isAvailable) {
|
|
10
|
+
let lxDebug = storageUtil.get('lxDebug');
|
|
11
|
+
try {
|
|
12
|
+
lxDebug = JSON.parse(lxDebug as string);
|
|
13
|
+
} catch {
|
|
14
|
+
lxDebug = 'true';
|
|
15
|
+
}
|
|
16
|
+
return new DebugDataStore(lxDebug === 'true' ? {} : (lxDebug as configTpe));
|
|
17
|
+
}
|
|
18
|
+
return null;
|
|
19
|
+
})();
|
|
20
|
+
|
|
21
|
+
export default debug;
|
|
@@ -2,15 +2,12 @@
|
|
|
2
2
|
import { SHA256 } from 'crypto-js';
|
|
3
3
|
import { v4 as uuidv4 } from 'uuid';
|
|
4
4
|
import config from '../config';
|
|
5
|
-
import { aesKey,
|
|
5
|
+
import { aesKey, reqIdKey } from '../const';
|
|
6
|
+
import debug from '../debug';
|
|
6
7
|
import { MODE, signHttpOptionsType } from '../types';
|
|
7
8
|
import { checkIsSignMode } from '../utils/check';
|
|
8
9
|
import message from '../utils/message';
|
|
9
|
-
import {
|
|
10
|
-
decodeQueryString,
|
|
11
|
-
obj2QueryString,
|
|
12
|
-
removeURLParameters,
|
|
13
|
-
} from '../utils/url';
|
|
10
|
+
import { decodeQueryString, obj2QueryString } from '../utils/url';
|
|
14
11
|
import { AESEncrypt } from './aes';
|
|
15
12
|
|
|
16
13
|
// 注意:修改此文件请跑测试用例, npm run test
|
|
@@ -37,7 +34,7 @@ import { AESEncrypt } from './aes';
|
|
|
37
34
|
|
|
38
35
|
// 由于X-B 的规则可能被业务网关使用,并往请求头增加内容,导致前后端加密不一致
|
|
39
36
|
// 2022.08.09 使用以下3个固定值 + X-LX-*匹配 方式
|
|
40
|
-
const hKeys = ['
|
|
37
|
+
const hKeys = ['x-b-auth', 'x-b-target-id', 'app-id'];
|
|
41
38
|
|
|
42
39
|
// 获取接口路径,2023-03-16调整,由于网关配置问题可能导致前后端取的服务地址不一致,调整后只取最后一级
|
|
43
40
|
const getApiPath = (url: string) => {
|
|
@@ -72,13 +69,16 @@ export const createHttpSignStr = (
|
|
|
72
69
|
let headerParams = '';
|
|
73
70
|
const headersKeyArr: any = [];
|
|
74
71
|
if (headers) {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
72
|
+
const includesHeaderKeys =
|
|
73
|
+
config.sign?.headerKeys?.map((item) => item.toLowerCase()) || hKeys;
|
|
74
|
+
Object.keys(headers).forEach((key) => {
|
|
75
|
+
if (
|
|
76
|
+
key.startsWith('X-LX-') ||
|
|
77
|
+
includesHeaderKeys.includes(key.toLowerCase())
|
|
78
|
+
) {
|
|
79
|
+
headersKeyArr.push(`${key.toLowerCase()}=${headers[key]}`);
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
82
|
}
|
|
83
83
|
headerParams = headersKeyArr.sort().join(';');
|
|
84
84
|
|
|
@@ -87,10 +87,11 @@ export const createHttpSignStr = (
|
|
|
87
87
|
// body为空时,可能出现前后端取值不一致问题。
|
|
88
88
|
// nodejs 一般存在空字符串、空对象、undefined、空表单 等,取决于框架处理和使用的中间件
|
|
89
89
|
// java后端一般为null
|
|
90
|
+
// 目前与后端约定默认为空字符串
|
|
90
91
|
let finallyBody = body;
|
|
91
|
-
if (
|
|
92
|
+
if (body === undefined || body === null) {
|
|
92
93
|
finallyBody =
|
|
93
|
-
|
|
94
|
+
typeof config.emptyBodyValue !== 'undefined' ? config.emptyBodyValue : '';
|
|
94
95
|
}
|
|
95
96
|
if (method.toLowerCase() === 'get') {
|
|
96
97
|
// 为保证与后端值一致此处需要将数据进行解码
|
|
@@ -114,7 +115,6 @@ export const createHttpSignStr = (
|
|
|
114
115
|
let result: string = '';
|
|
115
116
|
switch (signVersion) {
|
|
116
117
|
case MODE.SIGN:
|
|
117
|
-
case MODE.SIGN_KEY:
|
|
118
118
|
content = [
|
|
119
119
|
apiPath,
|
|
120
120
|
headerParams,
|
|
@@ -165,48 +165,17 @@ export const createHttpSignStr = (
|
|
|
165
165
|
message.log('url', url);
|
|
166
166
|
message.log('str', content);
|
|
167
167
|
message.log('sign', result);
|
|
168
|
+
|
|
169
|
+
if (headers?.[reqIdKey] && debug) {
|
|
170
|
+
debug.store(headers[reqIdKey], 'modeRequest', signVersion);
|
|
171
|
+
debug.store(headers[reqIdKey], 'url', url);
|
|
172
|
+
debug.store(headers[reqIdKey], 'str', content);
|
|
173
|
+
debug.store(headers[reqIdKey], 'sign', result);
|
|
174
|
+
}
|
|
168
175
|
}
|
|
169
176
|
|
|
170
177
|
// 返回约定签名
|
|
171
178
|
return result;
|
|
172
179
|
};
|
|
173
180
|
|
|
174
|
-
|
|
175
|
-
export const buildXSignUrl = (
|
|
176
|
-
url: string,
|
|
177
|
-
options: signHttpOptionsType = {},
|
|
178
|
-
version?: any,
|
|
179
|
-
) => {
|
|
180
|
-
if (!url) {
|
|
181
|
-
return '';
|
|
182
|
-
}
|
|
183
|
-
if (version && !checkIsSignMode(version)) {
|
|
184
|
-
message.warn(`不支持[${version}]签名模式`);
|
|
185
|
-
return url;
|
|
186
|
-
}
|
|
187
|
-
let _url = url;
|
|
188
|
-
const signVersion =
|
|
189
|
-
version || checkIsSignMode(config.mode as MODE)
|
|
190
|
-
? config.mode
|
|
191
|
-
: MODE.SIGN_WITH_TIME;
|
|
192
|
-
const signStr = createHttpSignStr(
|
|
193
|
-
url,
|
|
194
|
-
{ method: 'GET', ...options },
|
|
195
|
-
signVersion,
|
|
196
|
-
);
|
|
197
|
-
// 如果url上存在签名则移除原签名
|
|
198
|
-
if (
|
|
199
|
-
url.indexOf(signHeaderKey) !== -1 ||
|
|
200
|
-
url.indexOf(securityHeaderKey) !== -1
|
|
201
|
-
) {
|
|
202
|
-
_url = removeURLParameters(url, [signHeaderKey, securityHeaderKey]);
|
|
203
|
-
}
|
|
204
|
-
return `${_url}${
|
|
205
|
-
_url.includes('?') ? '&' : '?'
|
|
206
|
-
}${signHeaderKey}=${signStr}&${securityHeaderKey}=${signVersion}`;
|
|
207
|
-
};
|
|
208
|
-
|
|
209
|
-
// buildXSignUrl兼容平台内部使用,外部使用createHttpSignWithUrl
|
|
210
|
-
export const createHttpSignWithUrl = buildXSignUrl;
|
|
211
|
-
|
|
212
|
-
export default { createHttpSignStr, createHttpSignWithUrl };
|
|
181
|
+
export default { createHttpSignStr };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { securityType } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 移除内容里恶意html代码(xss攻击)
|
|
5
|
+
* @param str 待处理html内容
|
|
6
|
+
* @param options 可选配置项
|
|
7
|
+
* @return 安全的html片段
|
|
8
|
+
*/
|
|
9
|
+
const safeHTML: typeof securityType.html.safeHTML = (str, options) => {
|
|
10
|
+
if (typeof str !== 'string') return str || '';
|
|
11
|
+
const blacklist = options?.blackList || ['script', 'style', 'iframe'];
|
|
12
|
+
|
|
13
|
+
// 创建一个新的 DOM 解析器对象
|
|
14
|
+
const parser = new DOMParser();
|
|
15
|
+
|
|
16
|
+
// 使用 parseFromString 方法将 HTML 片段转换为 DOM 对象
|
|
17
|
+
const doc = parser.parseFromString(str, 'text/html');
|
|
18
|
+
|
|
19
|
+
// 遍历 DOM 树并删除恶意节点
|
|
20
|
+
function cleanNode(node: Element) {
|
|
21
|
+
if (node.nodeType === 1) {
|
|
22
|
+
// 元素节点
|
|
23
|
+
if (blacklist.indexOf(node.nodeName.toLowerCase()) !== -1) {
|
|
24
|
+
node.parentNode?.removeChild(node);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// 移除元素节点上所有事件属性
|
|
29
|
+
for (let i = node.attributes.length - 1; i >= 0; i -= 1) {
|
|
30
|
+
const attr = node.attributes[i];
|
|
31
|
+
if (
|
|
32
|
+
attr.name.startsWith('on') ||
|
|
33
|
+
String(node.getAttribute(attr.name))
|
|
34
|
+
.toLowerCase()
|
|
35
|
+
.indexOf('javascript:') !== -1
|
|
36
|
+
) {
|
|
37
|
+
node.removeAttribute(attr.name);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
for (let i = 0; i < node.childNodes.length; i += 1) {
|
|
43
|
+
cleanNode(node.childNodes[i] as Element);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
cleanNode(doc.body);
|
|
47
|
+
return doc.body.innerHTML;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export default {
|
|
51
|
+
safeHTML,
|
|
52
|
+
};
|
|
@@ -4,14 +4,8 @@
|
|
|
4
4
|
* @Description: 一个简单的http请求安全加密处理
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
// 使用方式1: 使用fetch请求模块,start({ mode: signKey }),适应经过封装的fetch模块
|
|
10
|
-
// 使用方式2: 使用fetch请求模块,将window.fetch 替换成 fetch,适应自己封装的fetch模块
|
|
11
|
-
// 使用方式3: 不使用fetch请求模块,使用createHttpSignStr自己获取签名,自行在header上添加参数
|
|
12
|
-
import merge from 'merge';
|
|
13
|
-
import capabilities from './clientCapabilities';
|
|
14
|
-
import config, { createDefaultConfig, setConfig } from './config';
|
|
7
|
+
import capabilities, { isBrowser } from './clientCapabilities';
|
|
8
|
+
import config, { setConfig } from './config';
|
|
15
9
|
import {
|
|
16
10
|
conflict as conflictFetch,
|
|
17
11
|
noConflict as noConflictFetch,
|
|
@@ -28,22 +22,48 @@ import type { configType } from './types';
|
|
|
28
22
|
import { checkIsModeValue } from './utils/check';
|
|
29
23
|
import message from './utils/message';
|
|
30
24
|
|
|
31
|
-
|
|
25
|
+
// 在浏览器模式下可能由于多个子工程集成造成多次conflict引发异常,在浏览器里需要将开关配置全局化
|
|
26
|
+
const _switch: Record<string, any> = {
|
|
27
|
+
_isHttpEncryption: false,
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
Object.defineProperty(
|
|
31
|
+
_switch,
|
|
32
|
+
'isHttpEncryption',
|
|
33
|
+
isBrowser
|
|
34
|
+
? {
|
|
35
|
+
get() {
|
|
36
|
+
return (window as any).isLxHttpEncryption ?? this._isHttpEncryption;
|
|
37
|
+
},
|
|
38
|
+
set(value) {
|
|
39
|
+
(window as any).isLxHttpEncryption = value;
|
|
40
|
+
this._isHttpEncryption = value;
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
: {
|
|
44
|
+
get() {
|
|
45
|
+
return this._isHttpEncryption;
|
|
46
|
+
},
|
|
47
|
+
set(value) {
|
|
48
|
+
this._isHttpEncryption = value;
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
);
|
|
52
|
+
|
|
32
53
|
const noConflictList: Function[] = [];
|
|
33
54
|
|
|
34
55
|
function start(startConfig?: configType) {
|
|
35
|
-
if (isHttpEncryption) {
|
|
36
|
-
|
|
37
|
-
return true;
|
|
56
|
+
if (_switch.isHttpEncryption) {
|
|
57
|
+
return null;
|
|
38
58
|
}
|
|
39
59
|
|
|
40
|
-
const _startConfig = merge.recursive({}, createDefaultConfig(), startConfig);
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (checkIsModeValue(mode)) {
|
|
44
|
-
isHttpEncryption = true;
|
|
60
|
+
// const _startConfig = merge.recursive({}, createDefaultConfig(), startConfig);
|
|
61
|
+
const mode = startConfig?.mode;
|
|
62
|
+
// 如果存在设置mode,校验mode,如果为空时,使用config预置的
|
|
63
|
+
if (!mode || checkIsModeValue(mode)) {
|
|
64
|
+
_switch.isHttpEncryption = true;
|
|
45
65
|
// 设置
|
|
46
|
-
setConfig(
|
|
66
|
+
setConfig(startConfig || {});
|
|
47
67
|
|
|
48
68
|
// 按需启动请求劫持
|
|
49
69
|
if (capabilities.fetch && config.requester?.includes('fetch')) {
|
|
@@ -58,15 +78,14 @@ function start(startConfig?: configType) {
|
|
|
58
78
|
conflictWxRequest();
|
|
59
79
|
noConflictList.push(noConflictWxRequest);
|
|
60
80
|
}
|
|
61
|
-
|
|
62
|
-
message.error(`http安全开启失败,不支持${mode}模式`);
|
|
81
|
+
return true;
|
|
63
82
|
}
|
|
64
|
-
|
|
65
|
-
return
|
|
83
|
+
message.error(`http安全开启失败,不支持${mode}模式`);
|
|
84
|
+
return false;
|
|
66
85
|
}
|
|
67
86
|
|
|
68
87
|
function stop() {
|
|
69
|
-
isHttpEncryption = false;
|
|
88
|
+
_switch.isHttpEncryption = false;
|
|
70
89
|
noConflictList.forEach((noConflict) => {
|
|
71
90
|
noConflict();
|
|
72
91
|
});
|
|
@@ -1,28 +1,36 @@
|
|
|
1
|
-
import { setConfig } from './config';
|
|
2
|
-
import KEYS from './const';
|
|
1
|
+
import { getConfig, initConfig, setConfig } from './config';
|
|
3
2
|
import { AESDecrypt, AESEncrypt } from './encipher/aes';
|
|
4
|
-
import { DESDecrypt, DESEncrypt } from './encipher/des';
|
|
5
3
|
import { RSADecrypt, RSAEncrypt } from './encipher/rsa';
|
|
6
|
-
import { createHttpSignStr
|
|
4
|
+
import { createHttpSignStr } from './encipher/sign';
|
|
7
5
|
import { checkToken, generateToken } from './encipher/token';
|
|
6
|
+
import html from './html';
|
|
8
7
|
import httpEncryption from './httpEncryption';
|
|
8
|
+
import {
|
|
9
|
+
autoSecurityWithUrl,
|
|
10
|
+
createEncryptedWithUrl,
|
|
11
|
+
createHttpSignWithUrl,
|
|
12
|
+
} from './urlEncryption';
|
|
9
13
|
import { lxEncrypt } from './utils/encrypted';
|
|
10
14
|
|
|
15
|
+
export { aesKey, rsaPrivKey, rsaPublicKey, signKey } from './const';
|
|
16
|
+
|
|
11
17
|
const security = {
|
|
12
18
|
httpEncryption,
|
|
13
19
|
createHttpSignStr,
|
|
14
20
|
createHttpSignWithUrl,
|
|
21
|
+
createEncryptedWithUrl,
|
|
22
|
+
autoSecurityWithUrl,
|
|
15
23
|
RSAEncrypt,
|
|
16
24
|
RSADecrypt,
|
|
17
25
|
AESEncrypt,
|
|
18
26
|
AESDecrypt,
|
|
19
|
-
DESEncrypt,
|
|
20
|
-
DESDecrypt,
|
|
21
|
-
KEYS,
|
|
22
27
|
checkToken,
|
|
23
28
|
generateToken,
|
|
24
29
|
setConfig,
|
|
30
|
+
getConfig,
|
|
31
|
+
initConfig,
|
|
25
32
|
lxEncrypt,
|
|
33
|
+
html,
|
|
26
34
|
};
|
|
27
35
|
|
|
28
36
|
export default security;
|