@polyv/request-plugin-aes 2.0.0
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/README.md +61 -0
- package/aes-plugin.d.ts +32 -0
- package/aes-plugin.js +111 -0
- package/config.d.ts +16 -0
- package/config.js +21 -0
- package/index.d.ts +4 -0
- package/index.js +4 -0
- package/package.json +13 -0
- package/request-options.d.ts +21 -0
- package/request-options.js +1 -0
- package/types.d.ts +19 -0
- package/types.js +1 -0
- package/utils.d.ts +8 -0
- package/utils.js +17 -0
package/README.md
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# AESRequestPlugin
|
|
2
|
+
|
|
3
|
+
用途:AES 加密插件,可对请求和响应数据进行 AES 加密和解密处理。
|
|
4
|
+
|
|
5
|
+
## 实例化参数
|
|
6
|
+
|
|
7
|
+
| 参数名 | 用途 | 类型 | 默认值 |
|
|
8
|
+
| - | - | - | - |
|
|
9
|
+
| `appId` | 应用 ID | `string` | - |
|
|
10
|
+
| `appSecret` | 应用密钥 | `string` | - |
|
|
11
|
+
| `encryptPostAES` | 是否对 POST 请求主体进行 AES 加密 | `boolean` | `true` |
|
|
12
|
+
|
|
13
|
+
## 请求选项
|
|
14
|
+
|
|
15
|
+
| 参数名 | 用途 | 类型 | 默认值 |
|
|
16
|
+
| - | - | - | - |
|
|
17
|
+
| `useAES` | 是否使用 AES 加密 | `boolean` | `true` |
|
|
18
|
+
| `encryptPostAES` | 是否对 POST 请求主体进行 AES 加密 | `boolean` | - |
|
|
19
|
+
|
|
20
|
+
## 使用方式
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import { PolyvRequest } from '@polyv/request-core';
|
|
24
|
+
import { AESRequestPlugin } from '@polyv/request-plugin-aes';
|
|
25
|
+
|
|
26
|
+
// 基础用法
|
|
27
|
+
const requester = new PolyvRequest({
|
|
28
|
+
requestPlugins: [
|
|
29
|
+
new AESRequestPlugin(),
|
|
30
|
+
]
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
// 配置应用 ID 和密钥(用于某些特殊接口的加密)
|
|
34
|
+
const requester = new PolyvRequest({
|
|
35
|
+
requestPlugins: [
|
|
36
|
+
new AESRequestPlugin({
|
|
37
|
+
appId: 'yourAppId',
|
|
38
|
+
appSecret: 'yourAppSecret',
|
|
39
|
+
}),
|
|
40
|
+
]
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// 禁用 POST 请求主体加密
|
|
44
|
+
const requester = new PolyvRequest({
|
|
45
|
+
requestPlugins: [
|
|
46
|
+
new AESRequestPlugin({
|
|
47
|
+
encryptPostAES: false,
|
|
48
|
+
}),
|
|
49
|
+
]
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// 在某个请求中禁用 AES 加密
|
|
53
|
+
requester.get('/api/data', {}, {
|
|
54
|
+
useAES: false,
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// 在某个请求中禁用 POST 请求主体加密
|
|
58
|
+
requester.post('/api/data', { name: 'test' }, {
|
|
59
|
+
encryptPostAES: false,
|
|
60
|
+
});
|
|
61
|
+
```
|
package/aes-plugin.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { RequestOptions, RequestPlugin, RequestResult } from '@polyv/request-core';
|
|
2
|
+
import { AESRequestPluginConfig } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* AES 请求插件
|
|
5
|
+
*/
|
|
6
|
+
export declare class AESRequestPlugin implements RequestPlugin {
|
|
7
|
+
private __config;
|
|
8
|
+
private __encryptPostAES;
|
|
9
|
+
constructor(__config?: AESRequestPluginConfig);
|
|
10
|
+
usePlugin(options: RequestOptions): boolean;
|
|
11
|
+
interceptIncludeParams(): object | void;
|
|
12
|
+
interceptEncryptRequest(options: RequestOptions): RequestOptions;
|
|
13
|
+
interceptDecryptResponse(result: RequestResult): RequestResult;
|
|
14
|
+
/**
|
|
15
|
+
* 处理 headers
|
|
16
|
+
* @param options 请求选项
|
|
17
|
+
*/
|
|
18
|
+
private __handleHeaders;
|
|
19
|
+
/**
|
|
20
|
+
* 处理 data
|
|
21
|
+
* @param options 请求选项
|
|
22
|
+
*/
|
|
23
|
+
private __handleData;
|
|
24
|
+
/**
|
|
25
|
+
* 获取解密 key
|
|
26
|
+
*/
|
|
27
|
+
private __getDecryptKeyInfo;
|
|
28
|
+
/**
|
|
29
|
+
* 获取加密 key
|
|
30
|
+
*/
|
|
31
|
+
private __getEncryptKeyInfo;
|
|
32
|
+
}
|
package/aes-plugin.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { INTERNAL_AES_DECRYPT_IV, INTERNAL_AES_DECRYPT_SIGN, INTERNAL_AES_ENCRYPT_IV, INTERNAL_AES_ENCRYPT_SIGN } from './config';
|
|
2
|
+
import { encryptTextCBC } from './utils';
|
|
3
|
+
import { decryptTextAES, AESDecryptType } from '@polyv/request-plugin-aes-decrypt';
|
|
4
|
+
// 1. 插件会在请求中自动添加 `encryptResponseType: 1` 参数,告知服务端需要返回加密数据
|
|
5
|
+
// 2. 对于 POST 请求,默认会对请求体进行 AES CBC 模式的加密,并添加 `x-e-type: 1` 请求头
|
|
6
|
+
// 3. 当服务端返回加密数据时(`encryption: true`),插件会自动对响应数据进行解密
|
|
7
|
+
// 4. 插件内部使用固定的加密和解密密钥,但如果请求中包含 `appId` 参数且与初始化配置的 `appId` 一致,则会使用配置的 `appSecret` 作为加密密钥
|
|
8
|
+
/**
|
|
9
|
+
* AES 请求插件
|
|
10
|
+
*/
|
|
11
|
+
export class AESRequestPlugin {
|
|
12
|
+
__config;
|
|
13
|
+
__encryptPostAES;
|
|
14
|
+
constructor(__config = {}) {
|
|
15
|
+
this.__config = __config;
|
|
16
|
+
this.__encryptPostAES = __config.encryptPostAES ?? true;
|
|
17
|
+
}
|
|
18
|
+
usePlugin(options) {
|
|
19
|
+
const { useAES = true } = options;
|
|
20
|
+
return useAES;
|
|
21
|
+
}
|
|
22
|
+
interceptIncludeParams() {
|
|
23
|
+
return {
|
|
24
|
+
// 插入 encryptResponseType 为 1,表示需要进行 aes 加密
|
|
25
|
+
encryptResponseType: 1,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
interceptEncryptRequest(options) {
|
|
29
|
+
// 处理 data
|
|
30
|
+
const data = this.__handleData(options);
|
|
31
|
+
// 处理 header
|
|
32
|
+
const headers = this.__handleHeaders(options);
|
|
33
|
+
return {
|
|
34
|
+
...options,
|
|
35
|
+
data,
|
|
36
|
+
headers,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
interceptDecryptResponse(result) {
|
|
40
|
+
const res = result.data;
|
|
41
|
+
if (!res.encryption || typeof res.data !== 'string') {
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
const data = res.data;
|
|
45
|
+
const decryptKeyInfo = this.__getDecryptKeyInfo();
|
|
46
|
+
res.data = decryptTextAES(data, decryptKeyInfo, AESDecryptType.Base64);
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 处理 headers
|
|
51
|
+
* @param options 请求选项
|
|
52
|
+
*/
|
|
53
|
+
__handleHeaders(options) {
|
|
54
|
+
const headers = (options.headers || {});
|
|
55
|
+
const { encryptPostAES = this.__encryptPostAES } = options;
|
|
56
|
+
if (options.method?.toLocaleUpperCase() === 'POST' && encryptPostAES) {
|
|
57
|
+
headers['x-e-type'] = 1;
|
|
58
|
+
}
|
|
59
|
+
return headers;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 处理 data
|
|
63
|
+
* @param options 请求选项
|
|
64
|
+
*/
|
|
65
|
+
__handleData(options) {
|
|
66
|
+
const data = options.data || {};
|
|
67
|
+
if (options.method?.toLocaleUpperCase() !== 'POST') {
|
|
68
|
+
return data;
|
|
69
|
+
}
|
|
70
|
+
let newData = data;
|
|
71
|
+
const { encryptPostAES = this.__encryptPostAES } = options;
|
|
72
|
+
if (encryptPostAES) {
|
|
73
|
+
// 强制使用 json 提交
|
|
74
|
+
options.requestType = 'json';
|
|
75
|
+
let targetText = '';
|
|
76
|
+
if (typeof data === 'string') {
|
|
77
|
+
targetText = data;
|
|
78
|
+
}
|
|
79
|
+
else if (typeof data === 'object') {
|
|
80
|
+
targetText = JSON.stringify(data);
|
|
81
|
+
}
|
|
82
|
+
const encryptKeyInfo = this.__getEncryptKeyInfo(options);
|
|
83
|
+
newData = encryptTextCBC(targetText, encryptKeyInfo);
|
|
84
|
+
}
|
|
85
|
+
return newData;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* 获取解密 key
|
|
89
|
+
*/
|
|
90
|
+
__getDecryptKeyInfo() {
|
|
91
|
+
return {
|
|
92
|
+
sign: INTERNAL_AES_DECRYPT_SIGN,
|
|
93
|
+
iv: INTERNAL_AES_DECRYPT_IV,
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 获取加密 key
|
|
98
|
+
*/
|
|
99
|
+
__getEncryptKeyInfo(options) {
|
|
100
|
+
const params = (options.params || {});
|
|
101
|
+
let sign = INTERNAL_AES_ENCRYPT_SIGN;
|
|
102
|
+
// 对于在 params 中传入了 appId 时,后端使用对应的 appSecret 进行解密
|
|
103
|
+
if ('appId' in params && params.appId === this.__config.appId && this.__config.appSecret) {
|
|
104
|
+
sign = this.__config.appSecret;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
sign,
|
|
108
|
+
iv: INTERNAL_AES_ENCRYPT_IV,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
package/config.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @ignore
|
|
3
|
+
*/
|
|
4
|
+
export declare const INTERNAL_AES_ENCRYPT_SIGN: string;
|
|
5
|
+
/**
|
|
6
|
+
* @ignore
|
|
7
|
+
*/
|
|
8
|
+
export declare const INTERNAL_AES_ENCRYPT_IV: string;
|
|
9
|
+
/**
|
|
10
|
+
* @ignore
|
|
11
|
+
*/
|
|
12
|
+
export declare const INTERNAL_AES_DECRYPT_SIGN: string;
|
|
13
|
+
/**
|
|
14
|
+
* @ignore
|
|
15
|
+
*/
|
|
16
|
+
export declare const INTERNAL_AES_DECRYPT_IV: string;
|
package/config.js
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { decode } from 'js-base64';
|
|
2
|
+
/**
|
|
3
|
+
* @ignore
|
|
4
|
+
*/
|
|
5
|
+
// 内部的 AES 加密签名:KLfO7ZnfQC8jIvEX
|
|
6
|
+
export const INTERNAL_AES_ENCRYPT_SIGN = decode('S0xmTzdabmZRQzhqSXZFWA==');
|
|
7
|
+
/**
|
|
8
|
+
* @ignore
|
|
9
|
+
*/
|
|
10
|
+
// 内部的 AES 加密偏移量:VTRe7SmdllRsJ7Cb
|
|
11
|
+
export const INTERNAL_AES_ENCRYPT_IV = decode('VlRSZTdTbWRsbFJzSjdDYg==');
|
|
12
|
+
/**
|
|
13
|
+
* @ignore
|
|
14
|
+
*/
|
|
15
|
+
// 内部的 AES 解密签名:PolyvApiResponse
|
|
16
|
+
export const INTERNAL_AES_DECRYPT_SIGN = decode('UG9seXZBcGlSZXNwb25zZQ==');
|
|
17
|
+
/**
|
|
18
|
+
* @ignore
|
|
19
|
+
*/
|
|
20
|
+
// 内部的 AES 解密偏移量:PolyvLiveEncrypt
|
|
21
|
+
export const INTERNAL_AES_DECRYPT_IV = decode('UG9seXZMaXZlRW5jcnlwdA==');
|
package/index.d.ts
ADDED
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@polyv/request-plugin-aes",
|
|
3
|
+
"version": "2.0.0",
|
|
4
|
+
"main": "./index.js",
|
|
5
|
+
"dependencies": {
|
|
6
|
+
"@polyv/request-core": "2.0.0",
|
|
7
|
+
"@polyv/request-plugin-aes-decrypt": "2.0.0",
|
|
8
|
+
"aes-js": "^3.1.2",
|
|
9
|
+
"crypto-js": "^4.1.1",
|
|
10
|
+
"js-base64": "^3.7.5"
|
|
11
|
+
},
|
|
12
|
+
"types": "./index.d.ts"
|
|
13
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface AESRequestOptions {
|
|
2
|
+
/**
|
|
3
|
+
* 是否使用 aes 加密
|
|
4
|
+
* @default true
|
|
5
|
+
* @plugin `AESRequestPlugin`
|
|
6
|
+
*/
|
|
7
|
+
useAES?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* 是否对 post 请求主体进行 aes 加密
|
|
10
|
+
* @plugin `AESRequestPlugin`
|
|
11
|
+
*/
|
|
12
|
+
encryptPostAES?: boolean;
|
|
13
|
+
}
|
|
14
|
+
declare module '@polyv/request-core' {
|
|
15
|
+
interface RequestCustomOptions extends AESRequestOptions {
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
declare module 'axios' {
|
|
19
|
+
interface AxiosRequestConfig extends AESRequestOptions {
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface AESRequestPluginConfig {
|
|
2
|
+
/**
|
|
3
|
+
* 应用 id
|
|
4
|
+
*/
|
|
5
|
+
appId?: string;
|
|
6
|
+
/**
|
|
7
|
+
* 应用密钥
|
|
8
|
+
*/
|
|
9
|
+
appSecret?: string;
|
|
10
|
+
/**
|
|
11
|
+
* 是否对 post 请求主体进行 aes 加密
|
|
12
|
+
* @default true
|
|
13
|
+
*/
|
|
14
|
+
encryptPostAES?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export interface AESInnerResData {
|
|
17
|
+
encryption: boolean;
|
|
18
|
+
data: unknown;
|
|
19
|
+
}
|
package/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/utils.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { AESKeyInfo } from '@polyv/request-plugin-aes-decrypt';
|
|
2
|
+
/**
|
|
3
|
+
* 加密数据(CBC 方式)
|
|
4
|
+
* @param targetText 目标文本
|
|
5
|
+
* @param encryptKeys 加密 key 信息
|
|
6
|
+
* @returns 加密后的密文
|
|
7
|
+
*/
|
|
8
|
+
export declare function encryptTextCBC(targetText: string, encryptKeys: AESKeyInfo): string;
|
package/utils.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import CryptoJS from 'crypto-js';
|
|
2
|
+
/**
|
|
3
|
+
* 加密数据(CBC 方式)
|
|
4
|
+
* @param targetText 目标文本
|
|
5
|
+
* @param encryptKeys 加密 key 信息
|
|
6
|
+
* @returns 加密后的密文
|
|
7
|
+
*/
|
|
8
|
+
export function encryptTextCBC(targetText, encryptKeys) {
|
|
9
|
+
const { sign, iv } = encryptKeys;
|
|
10
|
+
const cryptoKey = CryptoJS.enc.Utf8.parse(sign);
|
|
11
|
+
const secretData = CryptoJS.enc.Utf8.parse(targetText);
|
|
12
|
+
return CryptoJS.AES.encrypt(secretData, cryptoKey, {
|
|
13
|
+
iv: CryptoJS.enc.Utf8.parse(iv),
|
|
14
|
+
mode: CryptoJS.mode.CBC,
|
|
15
|
+
padding: CryptoJS.pad.Pkcs7
|
|
16
|
+
}).toString();
|
|
17
|
+
}
|