接口加密
This commit is contained in:
@@ -1,4 +1,6 @@
|
||||
import useUserStore from "../stores/useUserStore";
|
||||
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
|
||||
|
||||
import {
|
||||
request,
|
||||
createRequest,
|
||||
@@ -384,6 +386,14 @@ const formatTotal = (total) => {
|
||||
return `${roundedTotal}+`;
|
||||
};
|
||||
|
||||
export function sm2_Decrypt(word, key) {
|
||||
return SM.decrypt(word, key);
|
||||
}
|
||||
|
||||
export function sm2_Encrypt(word, key) {
|
||||
return SM.encrypt(word, key);
|
||||
}
|
||||
|
||||
export function formatDate(isoString) {
|
||||
const date = new Date(isoString);
|
||||
const year = date.getFullYear();
|
||||
@@ -1041,4 +1051,8 @@ export default {
|
||||
insertSortData,
|
||||
isInWechatMiniProgramWebview,
|
||||
isEmptyObject,
|
||||
sm4Decrypt,
|
||||
sm4Encrypt,
|
||||
sm2_Decrypt,
|
||||
sm2_Encrypt,
|
||||
}
|
||||
|
||||
13
config.js
13
config.js
@@ -6,8 +6,8 @@
|
||||
*/
|
||||
export default {
|
||||
// baseUrl: 'http://39.98.44.136:8080', // 测试
|
||||
baseUrl: 'https://www.xjksly.cn/api/ks', // 正式环境
|
||||
// baseUrl: 'http://ks.zhaopinzao8dian.com/api/ks', // 测试
|
||||
// baseUrl: 'https://www.xjksly.cn/api/ks', // 正式环境
|
||||
baseUrl: 'http://ks.zhaopinzao8dian.com/api/ks', // 测试
|
||||
|
||||
// LCBaseUrl:'http://10.110.145.145:9100',//内网端口
|
||||
// LCBaseUrlInner:'http://10.110.145.145:10100',//招聘、培训、帮扶
|
||||
@@ -88,5 +88,12 @@ export default {
|
||||
title: '找工作,用 AI 更高效|青岛市智能求职平台',
|
||||
desc: '融合海量岗位、智能简历匹配、竞争力分析,助你精准锁定理想职位!',
|
||||
imgUrl: 'https://qd.zhaopinzao8dian.com/file/csn/qd_shareLogo.jpg',
|
||||
}
|
||||
},
|
||||
// SM4 加密配置
|
||||
sm4Config: {
|
||||
key: '86C63180C1306ABC4D8F989E0A0BC9F3',
|
||||
mode: 'ECB',
|
||||
iv: 'UISwD9fW6cFh9SNS',
|
||||
cipherType: 'base64',
|
||||
},
|
||||
}
|
||||
|
||||
37
utils/crypto.js
Normal file
37
utils/crypto.js
Normal file
@@ -0,0 +1,37 @@
|
||||
import { sm4 } from 'sm-crypto';
|
||||
|
||||
export function sm4Decrypt(key, value, mode = "hex") {
|
||||
try {
|
||||
if (key.length !== 32) {
|
||||
uni.showToast({ title: '密钥必须是32位16进制字符串(128位)', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const decrypted = sm4.decrypt(value, key, {
|
||||
mode: 'ecb',
|
||||
cipherType: mode === 'hex' ? 'hex' : 'base64',
|
||||
padding: 'pkcs#5'
|
||||
});
|
||||
return decrypted;
|
||||
} catch (e) {
|
||||
console.error('sm4 decrypt error:', e);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
export function sm4Encrypt(key, value, mode = "hex") {
|
||||
try {
|
||||
if (key.length !== 32) {
|
||||
uni.showToast({ title: '密钥必须是32位16进制字符串(128位)', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
const encrypted = sm4.encrypt(value, key, {
|
||||
mode: 'ecb',
|
||||
cipherType: mode === 'hex' ? 'hex' : 'base64',
|
||||
padding: 'pkcs#5'
|
||||
});
|
||||
return encrypted;
|
||||
} catch (e) {
|
||||
console.error('sm4 encrypt error:', e);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,66 @@
|
||||
import config from "@/config.js"
|
||||
import { sm4Encrypt, sm4Decrypt } from '@/utils/crypto';
|
||||
import useUserStore from '@/stores/useUserStore';
|
||||
|
||||
const needToEncryptSet = new Set([
|
||||
'POST:/app/login',
|
||||
'GET:/app/user/resume',
|
||||
'POST:/app/user/resume',
|
||||
'POST:/app/user/experience/edit',
|
||||
'POST:/app/user/experience/delete',
|
||||
'GET:/app/user/experience/getSingle',
|
||||
'GET:/app/user/experience/list',
|
||||
'POST:/app/user/cert',
|
||||
'POST:/app/user/getUserArchives',
|
||||
]);
|
||||
|
||||
const encryptPathPrefixes = [
|
||||
'/app/common/',
|
||||
'/app/chat/',
|
||||
'/app/speech/',
|
||||
'/app/job/',
|
||||
'/app/company/',
|
||||
];
|
||||
|
||||
const isEncryptNeeded = (method, url) => {
|
||||
const key = `${method.toUpperCase()}:${url}`;
|
||||
if (needToEncryptSet.has(key)) return true;
|
||||
for (const encryptKey of needToEncryptSet) {
|
||||
const [encryptMethod, encryptUrl] = encryptKey.split(':');
|
||||
if (encryptMethod === method.toUpperCase() && url.startsWith(encryptUrl.split('/{')[0])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const prefix of encryptPathPrefixes) {
|
||||
if (url.startsWith(prefix)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
const encryptRequestData = (data) => {
|
||||
const jsonData = JSON.stringify(data);
|
||||
// const jsonData = JSON.stringify({a: '1'});
|
||||
console.log('[请求] 加密前:', jsonData)
|
||||
return {
|
||||
encrypted: true,
|
||||
encryptedData: sm4Encrypt(config.sm4Config.key, jsonData),
|
||||
timestamp: Date.now(),
|
||||
};
|
||||
};
|
||||
|
||||
const handleResponseData = (resData) => {
|
||||
try {
|
||||
if (resData?.encrypted) {
|
||||
const decrypted = sm4Decrypt(config.sm4Config.key, resData.encryptedData);
|
||||
resData = JSON.parse(decrypted);
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('[请求] 解密失败:', e.message);
|
||||
}
|
||||
return resData;
|
||||
};
|
||||
export function request({
|
||||
url,
|
||||
method = 'GET',
|
||||
@@ -89,25 +150,27 @@ export function createRequest(url, data = {}, method = 'GET', loading = false, h
|
||||
if(needHeader){
|
||||
header["Authorization"] = encodeURIComponent(Authorization);
|
||||
}
|
||||
const requestData = isEncryptNeeded(method, url) ? encryptRequestData(data) : data;
|
||||
return new Promise((resolve, reject) => {
|
||||
uni.request({
|
||||
url: config.baseUrl + url,
|
||||
method: method,
|
||||
data: data,
|
||||
data: requestData,
|
||||
header,
|
||||
success: resData => {
|
||||
// 响应拦截
|
||||
if (resData.statusCode === 200) {
|
||||
const responseData = handleResponseData(resData.data)
|
||||
const {
|
||||
code,
|
||||
msg
|
||||
} = resData.data
|
||||
} = responseData
|
||||
if (code === 200) {
|
||||
resolve(resData.data)
|
||||
resolve(responseData)
|
||||
return
|
||||
}
|
||||
// 处理业务错误
|
||||
if (resData.data?.code === 401 || resData.data?.code === 402) {
|
||||
if (responseData?.code === 401 || responseData?.code === 402) {
|
||||
useUserStore().logOut()
|
||||
}
|
||||
// 显示具体的错误信息
|
||||
|
||||
Reference in New Issue
Block a user