feat: 请求http工具支持接口加解密
This commit is contained in:
@@ -3,3 +3,6 @@ export const APP_REQUEST_HEADER_CODE = 'X-App-Code';
|
||||
|
||||
/**应用-请求头-系统版本 */
|
||||
export const APP_REQUEST_HEADER_VERSION = 'X-App-Version';
|
||||
|
||||
/**应用-请求数据-密钥 */
|
||||
export const APP_DATA_API_KEY = 'T9ox2DCzpLfJIPzkH9pKhsOTMOEMJcFv';
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
/**响应-code加密数据 */
|
||||
export const RESULT_CODE_ENCRYPT = 2;
|
||||
|
||||
/**响应-msg加密数据 */
|
||||
export const RESULT_MSG_ENCRYPT: Record<string, string> = {
|
||||
zh_CN: '加密!',
|
||||
en_US: 'encrypt!',
|
||||
};
|
||||
|
||||
/**响应-code正常成功 */
|
||||
export const RESULT_CODE_SUCCESS = 1;
|
||||
|
||||
|
||||
@@ -13,10 +13,13 @@ import {
|
||||
import {
|
||||
APP_REQUEST_HEADER_CODE,
|
||||
APP_REQUEST_HEADER_VERSION,
|
||||
APP_DATA_API_KEY,
|
||||
} from '@/constants/app-constants';
|
||||
import {
|
||||
RESULT_CODE_ENCRYPT,
|
||||
RESULT_CODE_ERROR,
|
||||
RESULT_CODE_SUCCESS,
|
||||
RESULT_MSG_ENCRYPT,
|
||||
RESULT_MSG_ERROR,
|
||||
RESULT_MSG_NOT_TYPE,
|
||||
RESULT_MSG_SERVER_ERROR,
|
||||
@@ -25,11 +28,12 @@ import {
|
||||
RESULT_MSG_URL_NOTFOUND,
|
||||
RESULT_MSG_URL_RESUBMIT,
|
||||
} from '@/constants/result-constants';
|
||||
import { decryptAES, encryptAES } from '@/utils/encrypt-utils';
|
||||
|
||||
/**响应结果类型 */
|
||||
export type ResultType = {
|
||||
/**响应码 */
|
||||
code: number | 1 | 0;
|
||||
code: number;
|
||||
/**信息 */
|
||||
msg: string;
|
||||
/**数据 */
|
||||
@@ -76,6 +80,8 @@ type OptionsType = {
|
||||
body?: BodyInit;
|
||||
/**防止数据重复提交 */
|
||||
repeatSubmit?: boolean;
|
||||
/**接口数据加密 */
|
||||
crypto?: boolean;
|
||||
/**携带授权Token请求头 */
|
||||
whithToken?: boolean;
|
||||
/**中断控制信号,timeout不会生效 */
|
||||
@@ -167,24 +173,40 @@ function beforeRequest(options: OptionsType): OptionsType | Promise<any> {
|
||||
|
||||
// 请求拼接地址栏参数
|
||||
if (options.params) {
|
||||
let paramStr = '';
|
||||
const params = options.params;
|
||||
const queryParams: string[] = [];
|
||||
for (const key in params) {
|
||||
const value = params[key];
|
||||
// 空字符或未定义的值不作为参数发送
|
||||
if (value === '' || value === undefined) continue;
|
||||
paramStr += `&${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||
const str = `${encodeURIComponent(key)}=${encodeURIComponent(value)}`;
|
||||
queryParams.push(str);
|
||||
}
|
||||
if (paramStr && paramStr.startsWith('&')) {
|
||||
options.url = `${options.url}?${paramStr.substring(1)}`;
|
||||
const paramStr = queryParams.join('&');
|
||||
if (paramStr) {
|
||||
const separator = options.url.includes('?') ? '&' : '?';
|
||||
// 请求加密
|
||||
if (options.crypto) {
|
||||
debugger;
|
||||
const data = encryptAES(JSON.stringify(paramStr), APP_DATA_API_KEY);
|
||||
options.url += `${separator}data=${encodeURIComponent(data)}`;
|
||||
} else {
|
||||
options.url += `${separator}${paramStr}`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 非get参数提交
|
||||
if (options.data instanceof FormData) {
|
||||
options.body = options.data;
|
||||
} else {
|
||||
options.body = JSON.stringify(options.data);
|
||||
let body = options.data
|
||||
if (body instanceof FormData) {
|
||||
options.body = body;
|
||||
} else if (body) {
|
||||
// 请求加密
|
||||
if (options.crypto) {
|
||||
const data = encryptAES(JSON.stringify(body), APP_DATA_API_KEY);
|
||||
body = { data };
|
||||
}
|
||||
options.body = JSON.stringify(body);
|
||||
}
|
||||
return options;
|
||||
}
|
||||
@@ -199,6 +221,28 @@ function interceptorResponse(res: ResultType): ResultType | Promise<any> {
|
||||
window.location.reload();
|
||||
}
|
||||
|
||||
// 响应数据解密
|
||||
if (res.code === RESULT_CODE_ENCRYPT) {
|
||||
const str = decryptAES(res.data, APP_DATA_API_KEY);
|
||||
let data = {};
|
||||
try {
|
||||
data = JSON.parse(str);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
if (Object.keys(data).length === 0) {
|
||||
return Promise.resolve({
|
||||
code: RESULT_CODE_ERROR,
|
||||
msg: RESULT_MSG_ENCRYPT[language],
|
||||
});
|
||||
}
|
||||
return Promise.resolve({
|
||||
code: RESULT_CODE_SUCCESS,
|
||||
msg: RESULT_MSG_SUCCESS[language],
|
||||
data,
|
||||
});
|
||||
}
|
||||
|
||||
// 风格处理
|
||||
if (!Reflect.has(res, 'code')) {
|
||||
return Promise.resolve({
|
||||
@@ -266,7 +310,7 @@ export async function request(options: OptionsType): Promise<ResultType> {
|
||||
case 'text': // 文本数据
|
||||
const str = await res.text();
|
||||
return {
|
||||
code: 1,
|
||||
code: RESULT_CODE_SUCCESS,
|
||||
msg: str,
|
||||
};
|
||||
case 'json': // json格式数据
|
||||
|
||||
50
src/utils/encrypt-utils.ts
Normal file
50
src/utils/encrypt-utils.ts
Normal file
@@ -0,0 +1,50 @@
|
||||
import CryptoJS from 'crypto-js';
|
||||
import { isValid, decode } from 'js-base64';
|
||||
|
||||
/**
|
||||
* AES 加密并转为 base64
|
||||
* @param plaintext 数据字符串
|
||||
* @param aeskey 密钥
|
||||
* @returns 加密字符串
|
||||
*/
|
||||
export function encryptAES(plaintext: string, aeskey: string): string {
|
||||
const nowRoaund = new Date().getTime().toString(6);
|
||||
const key = CryptoJS.enc.Utf8.parse(aeskey);
|
||||
const iv = CryptoJS.enc.Utf8.parse(nowRoaund);
|
||||
const encrypted = CryptoJS.AES.encrypt(`${nowRoaund}${plaintext}`, key, {
|
||||
iv: iv,
|
||||
blockSize: 16,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
format: CryptoJS.format.OpenSSL,
|
||||
});
|
||||
return encrypted.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* AES 解密
|
||||
* @param ciphertext 加密字符串
|
||||
* @param aeskey 密钥
|
||||
* @returns 数据字符串
|
||||
*/
|
||||
export function decryptAES(ciphertext: string, aeskey: string): string {
|
||||
const nowRoaund = new Date().getTime().toString(6);
|
||||
const key = CryptoJS.enc.Utf8.parse(aeskey);
|
||||
const iv = CryptoJS.enc.Utf8.parse(nowRoaund);
|
||||
const decrypted = CryptoJS.AES.decrypt(ciphertext, key, {
|
||||
iv: iv,
|
||||
blockSize: 16,
|
||||
mode: CryptoJS.mode.CBC,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
format: CryptoJS.format.OpenSSL,
|
||||
});
|
||||
const base64Str = decrypted.toString(CryptoJS.enc.Base64);
|
||||
if (isValid(base64Str)) {
|
||||
const str = decode(base64Str);
|
||||
const idx = str.indexOf(':)', 10);
|
||||
if (idx > 10) {
|
||||
return str.substring(idx + 2);
|
||||
}
|
||||
}
|
||||
return '';
|
||||
}
|
||||
Reference in New Issue
Block a user