添加前后端消息体加解密,responseBody requestBody,for get post put
parent
e9950929de
commit
1d05891b55
|
|
@ -8,6 +8,7 @@ import errorCode from './errorCode'
|
|||
|
||||
import { resetRouter } from '@/router'
|
||||
import { deleteUserCache } from '@/hooks/web/useCache'
|
||||
import securityUtils from "@/utils/securityUtils";
|
||||
|
||||
const tenantEnable = import.meta.env.VITE_APP_TENANT_ENABLE
|
||||
const { result_code, base_url, request_timeout } = config
|
||||
|
|
@ -71,6 +72,9 @@ service.interceptors.request.use(
|
|||
}
|
||||
}
|
||||
}
|
||||
if(method === 'POST' || method === 'GET' || method === 'PUT'){
|
||||
return securityUtils.gatewayRequest(config);
|
||||
}
|
||||
return config
|
||||
},
|
||||
(error: AxiosError) => {
|
||||
|
|
@ -85,6 +89,9 @@ service.interceptors.response.use(
|
|||
async (response: AxiosResponse<any>) => {
|
||||
let { data } = response
|
||||
const config = response.config
|
||||
if(config.headers!.ENCPARAMTER === 'true'){
|
||||
data = securityUtils.gatewayResponse(response);
|
||||
}
|
||||
if (!data) {
|
||||
// 返回“[HTTP]请求没有返回值”;
|
||||
throw new Error()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,333 @@
|
|||
import crypto from "crypto";
|
||||
import {JSEncrypt} from "jsencrypt";
|
||||
import CryptoJS from 'crypto-js'
|
||||
|
||||
|
||||
/** 全局变量配置-start **/
|
||||
const _publicKey = 'LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1NSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXkzREU2MEpCUUNCbG8xay9qRWlVcCtjeVc1OGYxMStML0xFcE1HZ0gwbzFzN1BjdzFpZG9WSm5OSUw5K1BMSnBoN2JFNUFzdWYycDZTWDZOU294NjIrMURaS0s2eUhNcFc2aEZYTlJmNG1BTEJQM0tXWlJHQjI2cU1nOXJ5Wnl3ejJFZzNlVGhMU1N0YjBJREtVWjJZbXp2N0tlSWE2K3pxaDFXeTcrcTlOcXIxQU9aU01vdjdGS3VHeTI4M21rSEVhckRxMlV6bFMzZnpsSk12THM4MG9qNWVtbTVWNE03ZmozUzZpNnVlajYybVlBZDFZT1NnZXVtRkpyblc3ZEhyaUhvazNIMEJ3NDI1ZExmREk3TkIzRXFEbU1xVytvYWFCK2U4aUMwbFFLU3hTeHVRS2Y0K2M3TWFtRmZOTjlrWmJpeUhyZUswM09iTkljbnlhMTBxd0lEQVFBQi0tLS0tRU5EIFBVQkxJQyBLRVktLS0tLQ=='
|
||||
// url白名单设置 暂无使用
|
||||
const whiteList = [
|
||||
"/tick/auth/login",
|
||||
"/k",
|
||||
"/cn",
|
||||
]
|
||||
|
||||
/** 全局变量配置-end **/
|
||||
|
||||
|
||||
|
||||
export default {
|
||||
|
||||
|
||||
/**
|
||||
* 读取信息
|
||||
*/
|
||||
get(key) {
|
||||
return sessionStorage.getItem(key)
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 添加信息
|
||||
*/
|
||||
set(key, value) {
|
||||
sessionStorage.setItem(key, value)
|
||||
},
|
||||
|
||||
/**
|
||||
* gateway网关验证信息处理(请求头)
|
||||
*/
|
||||
gatewayRequest(request) {
|
||||
let key = true;
|
||||
whiteList.find(function (value) {
|
||||
if (value === request.url) {
|
||||
key = false;
|
||||
}
|
||||
});
|
||||
|
||||
// 对非白名单请求进行处理
|
||||
if (key) {
|
||||
request.headers.ENCPARAMTER = 'true'; //提示后端要加解密
|
||||
|
||||
// 请求体数据
|
||||
let frontSecKEY = this.get("frontSecKEY")
|
||||
if(!frontSecKEY){ //不存在,则生成
|
||||
frontSecKEY = this.generateString(16);
|
||||
this.set("frontSecKEY",frontSecKEY);
|
||||
}
|
||||
//将临时生成的密钥发后端
|
||||
|
||||
let _pk = CryptoJS.enc.Utf8.stringify(CryptoJS.enc.Base64.parse(_publicKey));
|
||||
request.headers.frontSecKEY = this.rsaEncrypt(frontSecKEY, _pk); //base64转_publicKey回utf8来
|
||||
|
||||
// 使用此密钥将请求整体加密
|
||||
if(request.data){
|
||||
let _data = JSON.stringify(request.data);
|
||||
_data = this.encryptAES(_data, frontSecKEY);
|
||||
request.data =_data;
|
||||
}
|
||||
}
|
||||
|
||||
return request;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* gateway网关验证信息处理(响应头)
|
||||
*/
|
||||
gatewayResponse(response) {
|
||||
let key = true;
|
||||
|
||||
// 放置业务逻辑代码
|
||||
// response是服务器端返回来的数据信息,与Promise获得数据一致
|
||||
let data = response.data
|
||||
// config包含请求信息
|
||||
let config = response.config
|
||||
// 获取当前请求的url
|
||||
let url = config.url
|
||||
whiteList.find(function (value) {
|
||||
if (value === url) {
|
||||
key = false;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// 对非白名单数据进行整体解密处理
|
||||
if (key) {
|
||||
// 获取加密密钥,并传入解密组件进行解密
|
||||
let frontSecKEY = this.get("frontSecKEY")
|
||||
|
||||
// data = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data))
|
||||
data = this.decryptAES(data,frontSecKEY);
|
||||
|
||||
if (data != null && data !== "") {
|
||||
data = JSON.parse(data);
|
||||
}else {
|
||||
data = new Promise(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 判断 data 是否为对象
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
// 判断 data 是否匹配特定格式
|
||||
if (
|
||||
Object.prototype.hasOwnProperty.call(data, 'msg') &&
|
||||
Object.prototype.hasOwnProperty.call(data, 'code') &&
|
||||
typeof data.msg === 'string' &&
|
||||
typeof data.code === 'number'
|
||||
) {
|
||||
// 数据匹配特定格式
|
||||
if (data.code === 401) {
|
||||
sessionStorage.clear()
|
||||
|
||||
}
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
return data;
|
||||
},
|
||||
|
||||
/**
|
||||
* 用于生成aes密钥
|
||||
*
|
||||
*/
|
||||
generateString(length) {
|
||||
var result = '';
|
||||
var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
var charactersLength = characters.length;
|
||||
for (var i = 0; i < length; i++) {
|
||||
result += characters.charAt(Math.floor(Math.random() * charactersLength));
|
||||
}
|
||||
result = CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(result))
|
||||
return result;
|
||||
},
|
||||
/**
|
||||
* 用于网关请求 “/cn” 请求前的处理
|
||||
*
|
||||
* @returns {{ck: (string|null), k: string}}
|
||||
*/
|
||||
secureConnectionPrepare() {
|
||||
const publicKey = this.get("publicKey")
|
||||
const publicKeyMd5 = this.strToMd5(publicKey)
|
||||
let clientPublicKey = this.communication()
|
||||
clientPublicKey = this.rsaEncrypt(clientPublicKey, publicKey)
|
||||
return {
|
||||
"k": publicKeyMd5,
|
||||
"ck": clientPublicKey,
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 用于网关请求 “/cn” 请求后的处理
|
||||
*/
|
||||
secureConnection(data) {
|
||||
const privateKey = this.get("privateKey")
|
||||
data = this.rsaDecrypt(data, privateKey)
|
||||
data = JSON.parse(data)
|
||||
this.set("secretKey", data.secretKey)
|
||||
this.set("sessionId", data.sessionId)
|
||||
this.set("serverPublicKey", data.publicKey)
|
||||
},
|
||||
|
||||
//************************************网关通信-end
|
||||
|
||||
|
||||
/**
|
||||
* 生成公钥私钥对保存本地,并返回公钥
|
||||
*
|
||||
* @returns {string}
|
||||
*/
|
||||
communication() {
|
||||
const keys = this.rsaGenerateKey();
|
||||
const publicKey = keys.publicKey;
|
||||
const privateKey = keys.privateKey;
|
||||
this.set("privateKey", privateKey)
|
||||
|
||||
return publicKey
|
||||
},
|
||||
|
||||
//************************************公用加密方法-start
|
||||
|
||||
|
||||
/**
|
||||
* 将字符串取值MD5
|
||||
*
|
||||
* @param string 字符串对象
|
||||
* @returns {string} 字符串md5数值
|
||||
*/
|
||||
strToMd5(string) {
|
||||
// 规定使用哈希算法中的MD5算法
|
||||
const hash = crypto.createHash('md5');
|
||||
|
||||
// 可任意多次调用update(),效果相当于多个字符串相加
|
||||
hash.update(string);
|
||||
|
||||
// hash.digest('hex')表示输出的格式为16进制
|
||||
return hash.digest('hex');
|
||||
},
|
||||
//************************************公用加密方法-end
|
||||
|
||||
|
||||
//************************************AES对称加解密-start
|
||||
|
||||
|
||||
/**
|
||||
* AES对称加密数据
|
||||
*
|
||||
* @param {String} data 待加密的数据
|
||||
* @param {String} base64Key base64格式的密钥
|
||||
* @returns {String} 加密后的数据
|
||||
*/
|
||||
encryptAES(data, base64Key) {
|
||||
let encryptedBytes = null;
|
||||
if (data != null && base64Key != null) {
|
||||
const key = CryptoJS.enc.Base64.parse(base64Key);
|
||||
encryptedBytes = CryptoJS.AES.encrypt(data, key, {mode: CryptoJS.mode.ECB});
|
||||
encryptedBytes = encryptedBytes.toString();
|
||||
}
|
||||
return encryptedBytes;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* AES对称-解密数据
|
||||
*
|
||||
* @param {String} data 待解密的数据
|
||||
* @param {String} base64Key base64格式的密钥
|
||||
* @returns {String} 解密后的数据
|
||||
*/
|
||||
decryptAES(data, base64Key) {
|
||||
let decryptData = null;
|
||||
|
||||
if (data != null && base64Key != null) {
|
||||
const key = CryptoJS.enc.Base64.parse(base64Key)
|
||||
const decryptBytes = CryptoJS.AES.decrypt(data, key, {mode: CryptoJS.mode.ECB})
|
||||
decryptData = CryptoJS.enc.Utf8.stringify(decryptBytes);
|
||||
}
|
||||
|
||||
return decryptData
|
||||
},
|
||||
//************************************AES对称加解密-end
|
||||
|
||||
//************************************RSA非对称加解密-start
|
||||
/**
|
||||
* 非对称加解密-生成公钥与私钥
|
||||
*/
|
||||
rsaGenerateKey() {
|
||||
let keys = {
|
||||
"publicKey": "",
|
||||
"privateKey": "",
|
||||
}
|
||||
|
||||
// 创建 JSEncrypt 实例
|
||||
const encrypt = new JSEncrypt();
|
||||
|
||||
// 生成密钥对(公钥和私钥)
|
||||
const keyPair = encrypt.getKey();
|
||||
|
||||
// 获取公钥和私钥
|
||||
keys.publicKey = keyPair.getPublicBaseKeyB64();
|
||||
keys.privateKey = keyPair.getPrivateBaseKeyB64();
|
||||
|
||||
return keys
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 非对称加解密-公钥加密信息(分段加密)
|
||||
*
|
||||
* @param string 内容
|
||||
* @param publicKey 非对称私钥
|
||||
* @returns {string | null}
|
||||
*/
|
||||
rsaEncrypt(string, publicKey) {
|
||||
let encryptData = null;
|
||||
|
||||
if (string != null && publicKey != null) {
|
||||
const encryptor = new JSEncrypt({default_key_size:2048});
|
||||
encryptor.setPublicKey(publicKey);
|
||||
encryptData = encryptor.encrypt(string);
|
||||
}
|
||||
|
||||
return encryptData;
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* 非对称加解密-私钥解密信息(分段解密)
|
||||
*
|
||||
* @param string 加密内容
|
||||
* @param privateKey 非对称私钥
|
||||
* @returns {string | null}
|
||||
*/
|
||||
rsaDecrypt(string, privateKey) {
|
||||
let decryptData = null;
|
||||
if (string != null && privateKey != null) {
|
||||
|
||||
const encryptor = new JSEncrypt();
|
||||
encryptor.setPrivateKey(privateKey);
|
||||
// 根据私钥的长度确定块大小,一般为私钥长度减去一些填充长度
|
||||
const blockSize = 172;
|
||||
const encryptedLength = string.length;
|
||||
let decryptedBlocks = [];
|
||||
|
||||
// 拆分加密文本为块并逐个解密
|
||||
for (let i = 0; i < encryptedLength; i += blockSize) {
|
||||
const block = string.substr(i, blockSize);
|
||||
const decryptedBlock = encryptor.decrypt(block);
|
||||
decryptedBlocks.push(decryptedBlock);
|
||||
}
|
||||
decryptData = decryptedBlocks.join('')
|
||||
}
|
||||
|
||||
// 将解密的块合并为单个字符串
|
||||
return decryptData;
|
||||
},
|
||||
//************************************RSA非对称加解密-end
|
||||
}
|
||||
Loading…
Reference in New Issue