diff --git a/package.json b/package.json index 9880d7a..b21b255 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "normalize.css": "7.0.0", "nprogress": "0.2.0", "path-to-regexp": "2.4.0", + "sm-crypto": "^0.3.13", "sortablejs": "^1.14.0", "swiper": "^5.4.5", "v-emoji-picker": "^2.3.3", diff --git a/src/assets/js/utils/request.js b/src/assets/js/utils/request.js index 027a159..6818623 100644 --- a/src/assets/js/utils/request.js +++ b/src/assets/js/utils/request.js @@ -1,8 +1,10 @@ import axios from 'axios' -import { MessageBox, Message, Loading } from 'element-ui' +import { Loading, Message, MessageBox } from 'element-ui' import store from '@/store' import { getToken, removeToken } from '@/assets/js/utils/auth' import router from '@/router' +import { sm2 } from 'sm-crypto' +import { logger } from 'runjs/lib/common' // create an axios instance const service = axios.create({ @@ -10,6 +12,52 @@ const service = axios.create({ timeout: 600000 // request timeout }) +// SM2公钥 +const SM2_PUBLIC_KEY = + '3059301306072a8648ce3d020106082a811ccf5501822d0342000463c7ed894e2e4a1c2de4adb8b71c2fa15409356e6851d2f965ddd0e09283044fabb3457bad5a0cbb689d2668309cdb96f987716f0f83125d6f7fa6b295ac0e1f' +// SM2私钥 +const SM2_PRIVATE_KEY = + '308193020100301306072a8648ce3d020106082a811ccf5501822d0479307702010104203f5f667ca627d9a442fc5144cbd5ebd81d7fb66158665c7381186c93de4d8edfa00a06082a811ccf5501822da1440342000463c7ed894e2e4a1c2de4adb8b71c2fa15409356e6851d2f965ddd0e09283044fabb3457bad5a0cbb689d2668309cdb96f987716f0f83125d6f7fa6b295ac0e1f' + +// 不加密的URL列表 +const ENCRYPT_EXCLUDE_URLS = ['/bpic/ta/*'] + +// 将ENCRYPT_EXCLUDE_URLS通配符模式转换为正则表达式 +const excludePatterns = ENCRYPT_EXCLUDE_URLS.map(pattern => { + // 将 * 转换为 .* 用于正则匹配 + const regexPattern = pattern.replace(/\*/g, '.*') + return new RegExp('^' + regexPattern + '$') +}) +// 加密函数 +const encryptData = data => { + try { + const dataStr = JSON.stringify(data) + const encrypted = sm2.doEncrypt(dataStr, SM2_PUBLIC_KEY, 1) + // 使用加密模式1 + return { encrypted: encrypted } + } catch (e) { + return data // 失败时返回原始数据 + } +} + +// 解密函数 +const decryptData = encrypted => { + try { + const decrypted = sm2.doDecrypt(encrypted, SM2_PRIVATE_KEY, 1) + return JSON.parse(decrypted) + } catch (e) { + return encrypted // 失败时返回原始数据 + } +} + +// 检查是否需要加密 +const shouldEncrypt = config => { + // 获取url eg:/sysUserEx/baseLogin + const url = config.url.substring(config.url.lastIndexOf(':')).substring(6) + // 排除不加密的url + const isExcluded = excludePatterns.some(pattern => pattern.test(url)) + return !isExcluded +} let loading function startLoading() { //使用Element loading-start 方法 @@ -41,6 +89,19 @@ service.interceptors.request.use( config.headers['deviceId'] = localStorage.getItem('deviceId') } + // 加密处理 + if (shouldEncrypt(config)) { + // 添加加密标识l, 方便自测 + config.headers['X-Encrypted'] = 'true' + + if (config.data) { + // 保存原始数据用于调试 + config.originalData = config.data + config.data = encryptData(config.data) + console.log('config', config) + } + } + // config.type 可以从api的接口地址定义 可以不触发loading if (config.noLoading !== true) { startLoading() @@ -65,7 +126,15 @@ service.interceptors.response.use( ) { return response.data } - const res = response.data + let res = response.data + // 解密处理 + if (response.config.headers['X-Encrypted'] === 'true') { + try { + res = decryptData(res) + } catch (e) { + logger.error('解密响应失败', e) + } + } res.code = Number(res.code) if (res.code === 401) { MessageBox.confirm('登录状态已过期,请重新登录', '系统提示', {