@polyv/request-plugin-authorize-app-sign 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 +103 -0
- package/authorize-app-sign-plugin.d.ts +23 -0
- package/authorize-app-sign-plugin.js +88 -0
- package/index.d.ts +3 -0
- package/index.js +3 -0
- package/package.json +12 -0
- package/request-options.d.ts +27 -0
- package/request-options.js +1 -0
- package/types.d.ts +67 -0
- package/types.js +8 -0
- package/utils.d.ts +9 -0
- package/utils.js +23 -0
package/README.md
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# AuthorizeAppSignRequestPlugin
|
|
2
|
+
|
|
3
|
+
用途:应用签名授权插件,使用后会在所有请求中插入应用签名信息。
|
|
4
|
+
|
|
5
|
+
## 实例化参数
|
|
6
|
+
|
|
7
|
+
| 参数名 | 用途 | 类型 | 默认值 |
|
|
8
|
+
| - | - | - | - |
|
|
9
|
+
| `appId` | 应用 ID | `string` | - |
|
|
10
|
+
| `appSecret` | 应用密钥 | `string` | - |
|
|
11
|
+
| `signatureNonce` | 是否使用防重放 | `boolean` | `false` |
|
|
12
|
+
| `signatureMethod` | 签名方式 | `SignatureMethod` | `SignatureMethod.MD5` |
|
|
13
|
+
| `getAppSign` | 获取应用签名信息的方法 | `function` | - |
|
|
14
|
+
|
|
15
|
+
## 请求选项
|
|
16
|
+
|
|
17
|
+
| 参数名 | 用途 | 类型 | 默认值 |
|
|
18
|
+
| - | - | - | - |
|
|
19
|
+
| `useAppSign` | 是否使用应用签名授权 | `boolean` | `true` |
|
|
20
|
+
| `signatureNonce` | 是否使用防重放 | `boolean` | - |
|
|
21
|
+
| `signatureMethod` | 签名方式 | `SignatureMethod` | - |
|
|
22
|
+
|
|
23
|
+
## 应用签名信息类型
|
|
24
|
+
|
|
25
|
+
`AppSignData` 类型如下:
|
|
26
|
+
|
|
27
|
+
| 参数名 | 用途 | 类型 | 默认值 |
|
|
28
|
+
| - | - | - | - |
|
|
29
|
+
| `appId` | 应用 ID | `string` | - |
|
|
30
|
+
| `timestamp` | 签名的时间戳 | `number` | - |
|
|
31
|
+
| `sign` | 签名 | `string` | - |
|
|
32
|
+
| `signatureMethod` | 签名方式 | `SignatureMethod` | - |
|
|
33
|
+
|
|
34
|
+
## 使用方式
|
|
35
|
+
|
|
36
|
+
```js
|
|
37
|
+
import { PolyvRequest, SignatureMethod } from '@polyv/request-core';
|
|
38
|
+
import { AuthorizeAppSignRequestPlugin } from '@polyv/request-plugin-authorize-app-sign';
|
|
39
|
+
|
|
40
|
+
// 方式一:直接传入应用 ID 和密钥
|
|
41
|
+
const requester = new PolyvRequest({
|
|
42
|
+
requestPlugins: [
|
|
43
|
+
new AuthorizeAppSignRequestPlugin({
|
|
44
|
+
appId: 'yourAppId',
|
|
45
|
+
appSecret: 'yourAppSecret',
|
|
46
|
+
signatureMethod: SignatureMethod.MD5,
|
|
47
|
+
}),
|
|
48
|
+
]
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
// 方式二(推荐):自定义获取应用签名信息的方法
|
|
52
|
+
const requester = new PolyvRequest({
|
|
53
|
+
requestPlugins: [
|
|
54
|
+
new AuthorizeAppSignRequestPlugin({
|
|
55
|
+
getAppSign: async ({ params, signatureMethod }) => {
|
|
56
|
+
// 可以在这里实现自定义的签名逻辑
|
|
57
|
+
return {
|
|
58
|
+
appId: 'yourAppId',
|
|
59
|
+
timestamp: Date.now(),
|
|
60
|
+
sign: 'yourGeneratedSign',
|
|
61
|
+
signatureMethod,
|
|
62
|
+
};
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
]
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// 使用防重放机制
|
|
69
|
+
const requester = new PolyvRequest({
|
|
70
|
+
requestPlugins: [
|
|
71
|
+
new AuthorizeAppSignRequestPlugin({
|
|
72
|
+
appId: 'yourAppId',
|
|
73
|
+
appSecret: 'yourAppSecret',
|
|
74
|
+
signatureNonce: true,
|
|
75
|
+
}),
|
|
76
|
+
]
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// 如果你想在某个请求中使用不同的签名方式
|
|
80
|
+
requester.get('/api/data', {}, {
|
|
81
|
+
signatureMethod: SignatureMethod.SHA256,
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// 如果你想在某个请求中不使用应用签名授权
|
|
85
|
+
requester.get('/api/data', {}, {
|
|
86
|
+
useAppSign: false,
|
|
87
|
+
});
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## 签名处理逻辑
|
|
91
|
+
|
|
92
|
+
1. 插件会自动在请求中添加以下参数:
|
|
93
|
+
- `appId`: 应用 ID
|
|
94
|
+
- `timestamp`: 当前时间戳
|
|
95
|
+
- `sign`: 根据参数生成的签名
|
|
96
|
+
- `signatureMethod`: 签名方式(可选)
|
|
97
|
+
- `signatureNonce`: 防重放随机字符串(当启用防重放时)
|
|
98
|
+
|
|
99
|
+
2. 签名生成逻辑有两种方式:
|
|
100
|
+
- 通过传入的 `appId` 和 `appSecret` 自动生成
|
|
101
|
+
- 通过自定义的 `getAppSign` 方法生成
|
|
102
|
+
|
|
103
|
+
3. 当启用防重放机制时,每次请求会生成一个唯一的 `signatureNonce` 参数,用于防止请求被重放攻击
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { RequestOptions, RequestPlugin } from '@polyv/request-core';
|
|
2
|
+
import { AuthorizeAppSignRequestPluginConfig } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* 应用签名授权请求插件
|
|
5
|
+
*/
|
|
6
|
+
export declare class AuthorizeAppSignRequestPlugin implements RequestPlugin {
|
|
7
|
+
private __config;
|
|
8
|
+
/** 应用 id */
|
|
9
|
+
private __appId;
|
|
10
|
+
/** 应用密钥 */
|
|
11
|
+
private __appSecret;
|
|
12
|
+
/** 是否使用放重放 */
|
|
13
|
+
private __signatureNonce;
|
|
14
|
+
/** 签名方式 */
|
|
15
|
+
private __signatureMethod;
|
|
16
|
+
/** 获取应用签名信息 */
|
|
17
|
+
private __getAppSign?;
|
|
18
|
+
constructor(__config: AuthorizeAppSignRequestPluginConfig);
|
|
19
|
+
usePlugin(options: RequestOptions): boolean;
|
|
20
|
+
interceptIncludeParams(options: RequestOptions): object | undefined;
|
|
21
|
+
interceptAuthorizeRequest(options: RequestOptions): Promise<RequestOptions>;
|
|
22
|
+
private __getAppSignData;
|
|
23
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from 'uuid';
|
|
2
|
+
import { SignatureMethod } from './types';
|
|
3
|
+
import { getDataSign } from './utils';
|
|
4
|
+
/**
|
|
5
|
+
* 应用签名授权请求插件
|
|
6
|
+
*/
|
|
7
|
+
export class AuthorizeAppSignRequestPlugin {
|
|
8
|
+
__config;
|
|
9
|
+
/** 应用 id */
|
|
10
|
+
__appId;
|
|
11
|
+
/** 应用密钥 */
|
|
12
|
+
__appSecret;
|
|
13
|
+
/** 是否使用放重放 */
|
|
14
|
+
__signatureNonce;
|
|
15
|
+
/** 签名方式 */
|
|
16
|
+
__signatureMethod;
|
|
17
|
+
/** 获取应用签名信息 */
|
|
18
|
+
__getAppSign;
|
|
19
|
+
constructor(__config) {
|
|
20
|
+
this.__config = __config;
|
|
21
|
+
this.__appId = __config.appId || '';
|
|
22
|
+
this.__appSecret = __config.appSecret || '';
|
|
23
|
+
this.__signatureNonce = __config.signatureNonce ?? false;
|
|
24
|
+
this.__signatureMethod = __config.signatureMethod ?? SignatureMethod.MD5;
|
|
25
|
+
this.__getAppSign = __config.getAppSign;
|
|
26
|
+
}
|
|
27
|
+
usePlugin(options) {
|
|
28
|
+
const { useAppSign = true } = options;
|
|
29
|
+
return useAppSign;
|
|
30
|
+
}
|
|
31
|
+
interceptIncludeParams(options) {
|
|
32
|
+
const { signatureNonce = this.__signatureNonce, signatureMethod = this.__signatureMethod } = options;
|
|
33
|
+
const includeParams = {};
|
|
34
|
+
// 加入放重放参数
|
|
35
|
+
if (signatureNonce) {
|
|
36
|
+
includeParams.signatureNonce = uuidv4();
|
|
37
|
+
}
|
|
38
|
+
// 加入签名方式
|
|
39
|
+
if (signatureMethod) {
|
|
40
|
+
includeParams.signatureMethod = signatureMethod;
|
|
41
|
+
}
|
|
42
|
+
return includeParams;
|
|
43
|
+
}
|
|
44
|
+
async interceptAuthorizeRequest(options) {
|
|
45
|
+
const params = {
|
|
46
|
+
...(options.params || {}),
|
|
47
|
+
};
|
|
48
|
+
// 获取签名
|
|
49
|
+
const signData = await this.__getAppSignData(params, options);
|
|
50
|
+
if (signData) {
|
|
51
|
+
params.appId = signData.appId;
|
|
52
|
+
params.timestamp = signData.timestamp;
|
|
53
|
+
params.sign = signData.sign;
|
|
54
|
+
signData.signatureMethod && (params.signatureMethod = signData.signatureMethod);
|
|
55
|
+
}
|
|
56
|
+
else {
|
|
57
|
+
console.error('AuthorizeAppSignRequestPlugin error, signData is undefined');
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
...options,
|
|
61
|
+
params,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
async __getAppSignData(params, options) {
|
|
65
|
+
const { signatureMethod = this.__signatureMethod } = options;
|
|
66
|
+
if (this.__getAppSign) {
|
|
67
|
+
return await this.__getAppSign({
|
|
68
|
+
params,
|
|
69
|
+
signatureMethod,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
if (this.__appId && this.__appSecret) {
|
|
73
|
+
const timestamp = Date.now();
|
|
74
|
+
const targetData = {
|
|
75
|
+
...params,
|
|
76
|
+
appId: this.__appId,
|
|
77
|
+
timestamp,
|
|
78
|
+
};
|
|
79
|
+
const sign = getDataSign(targetData, this.__appSecret, signatureMethod);
|
|
80
|
+
return {
|
|
81
|
+
appId: this.__appId,
|
|
82
|
+
timestamp,
|
|
83
|
+
sign,
|
|
84
|
+
signatureMethod,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
package/index.d.ts
ADDED
package/index.js
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SignatureMethod } from './types';
|
|
2
|
+
export interface AuthorizeAppSignRequestOptions {
|
|
3
|
+
/**
|
|
4
|
+
* 是否使用应用签名授权
|
|
5
|
+
* @default true
|
|
6
|
+
* @plugin `AuthorizeAppSignRequestPlugin`
|
|
7
|
+
*/
|
|
8
|
+
useAppSign?: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* 是否使用放重放
|
|
11
|
+
* @plugin `AuthorizeAppSignRequestPlugin`
|
|
12
|
+
*/
|
|
13
|
+
signatureNonce?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* 签名方式
|
|
16
|
+
* @plugin `AuthorizeAppSignRequestPlugin`
|
|
17
|
+
*/
|
|
18
|
+
signatureMethod?: SignatureMethod;
|
|
19
|
+
}
|
|
20
|
+
declare module '@polyv/request-core' {
|
|
21
|
+
interface RequestCustomOptions extends AuthorizeAppSignRequestOptions {
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
declare module 'axios' {
|
|
25
|
+
interface AxiosRequestConfig extends AuthorizeAppSignRequestOptions {
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/types.d.ts
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { UniversalParams } from '@polyv/request-core';
|
|
2
|
+
/**
|
|
3
|
+
* 签名方式
|
|
4
|
+
*/
|
|
5
|
+
export declare enum SignatureMethod {
|
|
6
|
+
MD5 = "MD5",
|
|
7
|
+
SHA256 = "SHA256"
|
|
8
|
+
}
|
|
9
|
+
export interface AuthorizeAppSignRequestPluginConfig {
|
|
10
|
+
/**
|
|
11
|
+
* 应用 id
|
|
12
|
+
*/
|
|
13
|
+
appId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* 应用密钥
|
|
16
|
+
*/
|
|
17
|
+
appSecret?: string;
|
|
18
|
+
/**
|
|
19
|
+
* 是否使用放重放
|
|
20
|
+
* @default false
|
|
21
|
+
*/
|
|
22
|
+
signatureNonce?: boolean;
|
|
23
|
+
/**
|
|
24
|
+
* 签名方式
|
|
25
|
+
* @default SignatureMethod.MD5
|
|
26
|
+
*/
|
|
27
|
+
signatureMethod?: SignatureMethod;
|
|
28
|
+
/**
|
|
29
|
+
* 获取应用签名信息
|
|
30
|
+
*/
|
|
31
|
+
getAppSign?: GetAppSignFn;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 应用签名信息
|
|
35
|
+
*/
|
|
36
|
+
export interface AppSignData {
|
|
37
|
+
/**
|
|
38
|
+
* 应用 id
|
|
39
|
+
*/
|
|
40
|
+
appId: string;
|
|
41
|
+
/**
|
|
42
|
+
* 签名的时间戳
|
|
43
|
+
*/
|
|
44
|
+
timestamp: number;
|
|
45
|
+
/**
|
|
46
|
+
* 签名
|
|
47
|
+
*/
|
|
48
|
+
sign: string;
|
|
49
|
+
/**
|
|
50
|
+
* 签名方式
|
|
51
|
+
*/
|
|
52
|
+
signatureMethod: SignatureMethod;
|
|
53
|
+
}
|
|
54
|
+
export interface AppSignOptions {
|
|
55
|
+
/**
|
|
56
|
+
* 需要签名的参数
|
|
57
|
+
*/
|
|
58
|
+
params: UniversalParams;
|
|
59
|
+
/**
|
|
60
|
+
* 签名方式
|
|
61
|
+
*/
|
|
62
|
+
signatureMethod: SignatureMethod;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* 获取应用签名方法
|
|
66
|
+
*/
|
|
67
|
+
export type GetAppSignFn = (signOptions: AppSignOptions) => Promise<AppSignData> | AppSignData;
|
package/types.js
ADDED
package/utils.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { SignatureMethod } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* 获取对象 key 排序后的字符串
|
|
4
|
+
*/
|
|
5
|
+
export declare function getSortDataText(data: object): string;
|
|
6
|
+
/**
|
|
7
|
+
* 计算 sign 值
|
|
8
|
+
*/
|
|
9
|
+
export declare function getDataSign(data: object, secret: string, signatureMethod?: SignatureMethod): string;
|
package/utils.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import md5 from 'md5';
|
|
2
|
+
import sha256 from 'sha256';
|
|
3
|
+
import { SignatureMethod } from './types';
|
|
4
|
+
/**
|
|
5
|
+
* 获取对象 key 排序后的字符串
|
|
6
|
+
*/
|
|
7
|
+
export function getSortDataText(data) {
|
|
8
|
+
let text = '';
|
|
9
|
+
const keys = Object.keys(data).sort();
|
|
10
|
+
for (const key of keys) {
|
|
11
|
+
text += `${key}${data[key]}`;
|
|
12
|
+
}
|
|
13
|
+
return text;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 计算 sign 值
|
|
17
|
+
*/
|
|
18
|
+
export function getDataSign(data, secret, signatureMethod = SignatureMethod.MD5) {
|
|
19
|
+
const text = getSortDataText(data);
|
|
20
|
+
const cryptoText = secret + text + secret;
|
|
21
|
+
const sign = signatureMethod === SignatureMethod.MD5 ? md5(cryptoText) : sha256(cryptoText);
|
|
22
|
+
return sign.toUpperCase();
|
|
23
|
+
}
|