@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.
Files changed (27) hide show
  1. package/es/index.d.ts +5 -1
  2. package/es/index.js +107 -62
  3. package/lib/public/src/services/api/engine.ts +0 -2
  4. package/lib/public/src/utils/Security/clientCapabilities.ts +8 -0
  5. package/lib/public/src/utils/Security/config.ts +56 -49
  6. package/lib/public/src/utils/Security/const.ts +38 -127
  7. package/lib/public/src/utils/Security/debug/data.ts +86 -0
  8. package/lib/public/src/utils/Security/debug/index.ts +21 -0
  9. package/lib/public/src/utils/Security/encipher/sign.ts +25 -56
  10. package/lib/public/src/utils/Security/html.ts +52 -0
  11. package/lib/public/src/utils/Security/httpEncryption.ts +42 -23
  12. package/lib/public/src/utils/Security/index.ts +15 -7
  13. package/lib/public/src/utils/Security/requester/fetch.ts +87 -52
  14. package/lib/public/src/utils/Security/requester/wx.ts +60 -11
  15. package/lib/public/src/utils/Security/requester/xhr.ts +194 -40
  16. package/lib/public/src/utils/Security/types.ts +8 -90
  17. package/lib/public/src/utils/Security/urlEncryption.ts +108 -0
  18. package/lib/public/src/utils/Security/utils/atob.ts +34 -0
  19. package/lib/public/src/utils/Security/utils/caseInsensitive.ts +25 -0
  20. package/lib/public/src/utils/Security/utils/check.ts +27 -3
  21. package/lib/public/src/utils/Security/utils/cookie.ts +101 -53
  22. package/lib/public/src/utils/Security/utils/encrypted.ts +190 -43
  23. package/lib/public/src/utils/Security/utils/random.ts +21 -0
  24. package/lib/public/src/utils/Security/utils/storge.ts +22 -0
  25. package/lib/public/src/utils/Security/utils/url.ts +30 -5
  26. package/lib/public/src/utils/getSceneCode.ts +51 -0
  27. package/package.json +2 -2
@@ -1,8 +1,6 @@
1
- type requester = 'fetch' | 'xhr' | 'wxRequest';
1
+ export type requester = 'fetch' | 'xhr' | 'wxRequest';
2
2
 
3
3
  export const enum MODE {
4
- // 参数签名(旧数据)
5
- SIGN_KEY = 'signKey',
6
4
  // 参数签名
7
5
  SIGN = '1.0',
8
6
  // 时间限制性签名
@@ -17,21 +15,17 @@ export const enum MODE {
17
15
  RSA = '2.0',
18
16
  // AES参数加密
19
17
  AES = '3.0',
20
- // DES参数加密
21
- DES = '4.0',
22
18
  }
23
19
 
20
+ export type modeType = `${(typeof MODE)[keyof typeof MODE]}`;
21
+
24
22
  // 自定义加解密函数
25
23
  type EncryptionFunctionType = (
26
24
  content: string,
27
25
  key: string,
28
- CryptoJS: CryptoJS,
26
+ CryptoJS: any,
29
27
  ) => string;
30
28
 
31
- export type fnDESEncryptType = EncryptionFunctionType;
32
-
33
- export type fnDESDecryptType = EncryptionFunctionType;
34
-
35
29
  export type fnAESEncryptType = EncryptionFunctionType;
36
30
 
37
31
  export type fnAESDecryptType = EncryptionFunctionType;
@@ -39,13 +33,13 @@ export type fnAESDecryptType = EncryptionFunctionType;
39
33
  export type fnRSAEncryptType = (
40
34
  content: string,
41
35
  publicKey: string,
42
- JSEncrypt: JSEncrypt,
36
+ JSEncrypt: any,
43
37
  ) => string;
44
38
 
45
39
  export type fnRSADecryptType = (
46
40
  content: string,
47
41
  privKey: string,
48
- JSEncrypt: JSEncrypt,
42
+ JSEncrypt: any,
49
43
  ) => string;
50
44
 
51
45
  export declare namespace encipherOptionType {
@@ -54,7 +48,7 @@ export declare namespace encipherOptionType {
54
48
  saltKey?: string;
55
49
  saltValue?: string | Function;
56
50
  valueKeyName?: string;
57
- includeHeaders?: string[];
51
+ headerKeys?: string[];
58
52
  }
59
53
  interface aes {
60
54
  key?: string;
@@ -62,12 +56,6 @@ export declare namespace encipherOptionType {
62
56
  decrypt?: fnAESDecryptType;
63
57
  }
64
58
 
65
- interface des {
66
- key?: string;
67
- encrypt?: fnDESEncryptType;
68
- decrypt?: fnDESDecryptType;
69
- }
70
-
71
59
  interface rsa {
72
60
  privKey?: string;
73
61
  publicKey?: string;
@@ -78,13 +66,12 @@ export declare namespace encipherOptionType {
78
66
 
79
67
  type ignoreSupportType = string | RegExp | Function;
80
68
  export interface configType {
81
- mode?: MODE;
69
+ mode?: modeType;
82
70
  securityHeaderKey?: string;
83
71
  requester?: requester | requester[];
84
72
  ignore?: ignoreSupportType | ignoreSupportType[];
85
73
  sign?: encipherOptionType.sign;
86
74
  aes?: encipherOptionType.aes;
87
- des?: encipherOptionType.des;
88
75
  rsa?: encipherOptionType.rsa;
89
76
  timeDeviation?: number;
90
77
  debug?: boolean;
@@ -108,72 +95,3 @@ export interface signHttpOptionsType {
108
95
  search?: string | any;
109
96
  saltValue?: string;
110
97
  }
111
-
112
- namespace securityType {
113
- export interface httpEncryption {
114
- start: (startConfig?: configType) => void;
115
- stop: () => void;
116
- }
117
-
118
- export function createHttpSignStr(
119
- url: string,
120
- options: signHttpOptionsType,
121
- version?: any,
122
- ): string;
123
-
124
- export function createHttpSignWithUrl(
125
- url: string,
126
- options?: signHttpOptionsType,
127
- version?: any,
128
- ): string;
129
-
130
- export function RSAEncrypt(
131
- content: string,
132
- publicKey: string,
133
- handle?: fnRSAEncryptType,
134
- ): string;
135
-
136
- export function RSADecrypt(
137
- content: string,
138
- privKey: string,
139
- handle?: fnRSADecryptType,
140
- ): string;
141
-
142
- export function AESEncrypt(
143
- content: string,
144
- aesKey: string,
145
- handle?: fnAESEncryptType,
146
- ): string;
147
-
148
- export function AESDecrypt(
149
- content: string,
150
- aesKey: string,
151
- handle?: fnAESDecryptType,
152
- ): string;
153
-
154
- export function DESEncrypt(
155
- content: string,
156
- desKey: string,
157
- handle?: fnDESEncryptType,
158
- ): string;
159
-
160
- export function DESDecrypt(
161
- content: string,
162
- desKey: string,
163
- handle?: fnDESDecryptType,
164
- ): string;
165
-
166
- export function setConfig(config: configType): void;
167
-
168
- export function lxEncrypt(str: string): string;
169
-
170
- export type httpEncryptionConfigType = typeof configType;
171
-
172
- export type KEYS = {
173
- signKey: string;
174
- rsaPublicKey: string;
175
- rsaPrivKey: string;
176
- aesKey: string;
177
- desKey: string;
178
- };
179
- }
@@ -0,0 +1,108 @@
1
+ import config from './config';
2
+ import { securityHeaderKey, signHeaderKey } from './const';
3
+ import { createHttpSignStr } from './encipher/sign';
4
+ import { MODE, modeType, securityType } from './types';
5
+ import { checkIsEncryption, checkIsSignMode } from './utils/check';
6
+ import {
7
+ decryptedStrForSearchParams,
8
+ encryptedStrForSearchParams,
9
+ } from './utils/encrypted';
10
+ import message from './utils/message';
11
+ import { getSearchObj, removeURLParameters } from './utils/url';
12
+
13
+ export const createHttpSignWithUrl: typeof securityType.createHttpSignWithUrl =
14
+ (url, options = {}, version) => {
15
+ if (!url) {
16
+ return '';
17
+ }
18
+ if (version && !checkIsSignMode(version)) {
19
+ message.warn(`不支持[${version}]签名模式`);
20
+ return url;
21
+ }
22
+ let _url = url;
23
+ const signVersion =
24
+ version ||
25
+ (checkIsSignMode(config.mode as MODE)
26
+ ? config.mode
27
+ : MODE.SIGN_WITH_TIME);
28
+ const signStr = createHttpSignStr(
29
+ url,
30
+ { method: 'GET', ...options },
31
+ signVersion,
32
+ );
33
+ // 如果url上存在签名则移除原签名
34
+ if (
35
+ url.indexOf(signHeaderKey) !== -1 ||
36
+ url.indexOf(securityHeaderKey) !== -1
37
+ ) {
38
+ _url = removeURLParameters(url, [signHeaderKey, securityHeaderKey]);
39
+ }
40
+ return `${_url}${
41
+ _url.includes('?') ? '&' : '?'
42
+ }${signHeaderKey}=${signStr}&${securityHeaderKey}=${signVersion}`;
43
+ };
44
+
45
+ /**
46
+ * 将url里的参数进行加密
47
+ * @param url url地址
48
+ * @param version 加密模式
49
+ * @returns 加密处理后的url地址(带加密模式标记)
50
+ */
51
+ export const createEncryptedWithUrl: typeof securityType.createEncryptedWithUrl =
52
+ (url, version) => {
53
+ if (!url) {
54
+ return '';
55
+ }
56
+ if (version && !checkIsEncryption(version)) {
57
+ return url;
58
+ }
59
+ if (url.indexOf('?') !== -1) {
60
+ const encryptedMode = version || '3.0';
61
+ return `${url.replace(/[^?]+$/g, (data) =>
62
+ encryptedStrForSearchParams(data, encryptedMode),
63
+ )}&${securityHeaderKey}=${encryptedMode}`;
64
+ }
65
+ return url;
66
+ };
67
+
68
+ export const autoSecurityWithUrl: typeof securityType.autoSecurityWithUrl = (
69
+ url,
70
+ options,
71
+ ) => {
72
+ let originUrl: string = url;
73
+ const securityHeaderKey = config.securityHeaderKey as string;
74
+ const confiMode = config.mode as modeType;
75
+ const modeInUrl = getSearchObj(url)[securityHeaderKey];
76
+ const finallyMode =
77
+ typeof options?.modeRule === 'function'
78
+ ? options.modeRule(confiMode)
79
+ : confiMode;
80
+ // 处理旧模式url
81
+ if (modeInUrl) {
82
+ if (checkIsEncryption(modeInUrl)) {
83
+ if (finallyMode === modeInUrl) {
84
+ // 如果地址处理前后均为相同加密方式则不需处理
85
+ return url;
86
+ }
87
+ // 否则对url进行解密并移除旧模式参数标识
88
+ originUrl = removeURLParameters(url, [securityHeaderKey]).replace(
89
+ /[^?]+$/g,
90
+ (data) => decryptedStrForSearchParams(data, modeInUrl),
91
+ );
92
+ } else if (checkIsSignMode(modeInUrl)) {
93
+ // 移除旧模式参数标识
94
+ originUrl = removeURLParameters(url, [
95
+ config.sign?.valueKeyName as string,
96
+ securityHeaderKey,
97
+ ]);
98
+ }
99
+ }
100
+ // 执行加签或加密处理
101
+ if (checkIsSignMode(finallyMode)) {
102
+ return createHttpSignWithUrl(originUrl, {}, finallyMode);
103
+ }
104
+ if (checkIsEncryption(finallyMode)) {
105
+ return createEncryptedWithUrl(originUrl, finallyMode as '2.0' | '3.0');
106
+ }
107
+ return originUrl;
108
+ };
@@ -0,0 +1,34 @@
1
+ /* eslint-disable no-bitwise */
2
+ /* eslint-disable no-plusplus */
3
+
4
+ const customAtob = (str: string) => {
5
+ if (typeof atob === 'function') {
6
+ return atob(str);
7
+ }
8
+ const base64 =
9
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
10
+ let result = '';
11
+
12
+ for (let i = 0; i < str.length; ) {
13
+ const char1 = base64.indexOf(str.charAt(i++));
14
+ const char2 = base64.indexOf(str.charAt(i++));
15
+ const char3 = base64.indexOf(str.charAt(i++));
16
+ const char4 = base64.indexOf(str.charAt(i++));
17
+
18
+ const byte1 = (char1 << 2) | (char2 >> 4);
19
+ const byte2 = ((char2 & 15) << 4) | (char3 >> 2);
20
+ const byte3 = ((char3 & 3) << 6) | char4;
21
+
22
+ result += String.fromCharCode(byte1);
23
+
24
+ if (char3 !== 64) {
25
+ result += String.fromCharCode(byte2);
26
+ }
27
+ if (char4 !== 64) {
28
+ result += String.fromCharCode(byte3);
29
+ }
30
+ }
31
+ return result;
32
+ };
33
+
34
+ export default customAtob;
@@ -0,0 +1,25 @@
1
+ // 大小写不敏感函数
2
+
3
+ /**
4
+ * 获取对象属性值,忽略大小写
5
+ * @param data 待获取数据的对象数据
6
+ * @param attr 属性名称
7
+ * @returns
8
+ */
9
+ export const getObjectValue = (data: Record<any, any>, attr: string): any => {
10
+ if (typeof attr === 'undefined' || typeof data === 'undefined')
11
+ return undefined;
12
+ // 优先通过attr直接获取数据,如果数据不存在,则进行小写转换再获取
13
+ let result = data[attr];
14
+ if (typeof result === 'undefined') {
15
+ const lowerAttr = attr.toLowerCase();
16
+ const objectKeys = Object.keys(data);
17
+ for (let i = 0; i < objectKeys.length; i += 1) {
18
+ if (objectKeys[i].toLowerCase() === lowerAttr) {
19
+ result = data[objectKeys[i]];
20
+ break;
21
+ }
22
+ }
23
+ }
24
+ return result;
25
+ };
@@ -3,7 +3,6 @@ import { MODE } from '../types';
3
3
 
4
4
  const signModes: string[] = [
5
5
  MODE.SIGN,
6
- MODE.SIGN_KEY,
7
6
  MODE.SIGN_UUID,
8
7
  MODE.SIGN_UUID_WITHOUT_SALT,
9
8
  MODE.SIGN_WITHOUT_SALT,
@@ -11,28 +10,53 @@ const signModes: string[] = [
11
10
  ];
12
11
  const signModesWithSalt: string[] = [
13
12
  MODE.SIGN,
14
- MODE.SIGN_KEY,
15
13
  MODE.SIGN_UUID,
16
14
  MODE.SIGN_WITH_TIME,
17
15
  ];
18
- const encryptionModes: string[] = [MODE.AES, MODE.DES, MODE.RSA];
16
+ const encryptionModes: string[] = [MODE.AES, MODE.RSA];
19
17
 
18
+ /**
19
+ * 检查安全模式是否为加签
20
+ * @param mode 模式值
21
+ * @returns boolean
22
+ */
20
23
  export const checkIsSignMode = (mode: string): boolean => {
21
24
  return signModes.includes(mode);
22
25
  };
23
26
 
27
+ /**
28
+ * 检查安全模式是否为加签(带盐值)
29
+ * @param mode 模式值
30
+ * @returns boolean
31
+ */
24
32
  export const checkIsSignWithSalt = (mode: string): boolean => {
25
33
  return signModesWithSalt.includes(mode);
26
34
  };
27
35
 
36
+ /**
37
+ * 检查安全模式是否为加密
38
+ * @param mode 模式值
39
+ * @returns boolean
40
+ */
28
41
  export const checkIsEncryption = (mode: string): boolean => {
29
42
  return encryptionModes.includes(mode);
30
43
  };
31
44
 
45
+ /**
46
+ * 检查安全模式是否为合法值
47
+ * @param mode 模式值
48
+ * @returns boolean
49
+ */
32
50
  export const checkIsModeValue = (mode: string): boolean => {
33
51
  return signModes.includes(mode) || encryptionModes.includes(mode);
34
52
  };
35
53
 
54
+ /**
55
+ * 检查当前请求是否需要忽略
56
+ * @param url 请求地址
57
+ * @param options 请求参数
58
+ * @returns boolean
59
+ */
36
60
  export const checkIsUrlIgnore = (
37
61
  url: string,
38
62
  options?: { headers?: any; body?: any; method?: string },
@@ -1,70 +1,118 @@
1
- import capabilities from '../clientCapabilities';
2
- import message from './message';
3
-
4
- const showError = () => message.warn('[lcdp-security]: 当前环境不支持cookie');
5
-
6
1
  const CookieUtil = {
7
- get(name: string) {
8
- if (!capabilities.cookie) {
9
- showError();
10
- return null;
11
- }
12
- const cookieName: string = `${encodeURIComponent(name)}=`;
13
- const cookieStart: number = document.cookie.indexOf(cookieName);
14
- let cookieValue: string | null = null;
15
- let cookieEnd: number;
16
-
17
- if (cookieStart > -1) {
18
- cookieEnd = document.cookie.indexOf(';', cookieStart);
19
- if (cookieEnd === -1) {
20
- cookieEnd = document.cookie.length;
21
- }
22
- cookieValue = decodeURIComponent(
23
- document.cookie.substring(cookieStart + cookieName.length, cookieEnd),
24
- );
25
- }
26
-
27
- return cookieValue;
2
+ /**
3
+ * 获取cookie
4
+ * @param key cookie字段名称
5
+ * @returns cookie值
6
+ */
7
+ getItem(key: string) {
8
+ return (
9
+ decodeURIComponent(
10
+ document.cookie.replace(
11
+ new RegExp(
12
+ `(?:(?:^|.*;)\\s*${encodeURIComponent(key).replace(
13
+ /[-.+*]/g,
14
+ '\\$&',
15
+ )}\\s*\\=\\s*([^;]*).*$)|^.*$`,
16
+ ),
17
+ '$1',
18
+ ),
19
+ ) || null
20
+ );
28
21
  },
29
22
 
30
- set(
31
- name: string,
23
+ /**
24
+ * 设置cookie值
25
+ * @param key cookie字段名称
26
+ * @param value 值
27
+ * @param end 有效结束事件
28
+ * @param path 作用域-路径
29
+ * @param domain 作用域-域名
30
+ * @param secure 是否只通过 https 协议传输
31
+ * @returns 设置成功返回true,设置失败返回false
32
+ */
33
+ setItem(
34
+ key: string,
32
35
  value: string,
33
- expires: Date,
34
- path: string,
35
- domain: string,
36
- secure: boolean,
36
+ end?: any,
37
+ path?: string,
38
+ domain?: string,
39
+ secure?: boolean,
37
40
  ) {
38
- if (!capabilities.cookie) {
39
- showError();
40
- return;
41
- }
42
- let cookieText = `${encodeURIComponent(name)}=${encodeURIComponent(value)}`;
43
-
44
- if (expires instanceof Date) {
45
- cookieText += `; expires=${expires.toUTCString()}`;
46
- }
47
-
48
- if (path) {
49
- cookieText += `; path=${path}`;
41
+ if (!key || /^(?:expires|max\-age|path|domain|secure)$/i.test(key)) {
42
+ return false;
50
43
  }
51
-
52
- if (domain) {
53
- cookieText += `; domain=${domain}`;
44
+ let expires = '';
45
+ if (end) {
46
+ switch (end.constructor) {
47
+ case Number:
48
+ expires =
49
+ end === Infinity
50
+ ? '; expires=Fri, 31 Dec 9999 23:59:59 GMT'
51
+ : `; max-age=${end}`;
52
+ break;
53
+ case String:
54
+ expires = `; expires=${end}`;
55
+ break;
56
+ case Date:
57
+ expires = `; expires=${end.toUTCString()}`;
58
+ break;
59
+ default:
60
+ break;
61
+ }
54
62
  }
63
+ document.cookie = `${encodeURIComponent(key)}=${encodeURIComponent(
64
+ value,
65
+ )}${expires}${domain ? `; domain=${domain}` : ''}${
66
+ path ? `; path=${path}` : ''
67
+ }${secure ? '; secure' : ''}`;
68
+ return true;
69
+ },
55
70
 
56
- if (secure) {
57
- cookieText += '; secure';
71
+ /**
72
+ * 删除cookie指定项
73
+ * @param key cookie字段名称
74
+ * @param path cookie所在作用域-路径
75
+ * @param domain cookie所在作用域-域名
76
+ * @returns 删除成功返回true,删除失败返回false
77
+ */
78
+ removeItem(key: string, path?: string, domain?: string) {
79
+ if (!key || !this.hasItem(key)) {
80
+ return false;
58
81
  }
82
+ document.cookie = `${encodeURIComponent(
83
+ key,
84
+ )}=; expires=Thu, 01 Jan 1970 00:00:00 GMT${
85
+ domain ? `; domain=${domain}` : ''
86
+ }${path ? `; path=${path}` : ''}`;
87
+ return true;
88
+ },
59
89
 
60
- document.cookie = cookieText;
90
+ /**
91
+ * 是否包含cookie项
92
+ * @param key cookie字段名称
93
+ * @returns 存在返回true,不存在返回false
94
+ */
95
+ hasItem(key: string) {
96
+ return new RegExp(
97
+ `(?:^|;\\s*)${encodeURIComponent(key).replace(/[-.+*]/g, '\\$&')}\\s*\\=`,
98
+ ).test(document.cookie);
61
99
  },
62
100
 
63
- unset(name: string, path: string, domain: string, secure: boolean) {
64
- this.set(name, '', new Date(0), path, domain, secure);
101
+ /**
102
+ * 获取cookie里所有字段名称
103
+ * @returns 字段名称列表
104
+ */
105
+ keys() {
106
+ const aKeys = document.cookie
107
+ .replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, '')
108
+ .split(/\s*(?:\=[^;]*)?;\s*/);
109
+ for (let nIdx = 0; nIdx < aKeys.length; nIdx += 1) {
110
+ aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]);
111
+ }
112
+ return aKeys;
65
113
  },
66
114
  };
67
115
 
68
- export const getSaltValue = (saltKey: string) => CookieUtil.get(saltKey);
116
+ export const getSaltValue = (saltKey: string) => CookieUtil.getItem(saltKey);
69
117
 
70
118
  export default CookieUtil;