feat: 请求http工具支持接口加解密

This commit is contained in:
TsMask
2024-08-15 10:08:12 +08:00
parent 19b77ed005
commit aa07b51663
4 changed files with 116 additions and 10 deletions

View File

@@ -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';

View File

@@ -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;

View File

@@ -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格式数据

View 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 '';
}