数据加密与问题修复

This commit is contained in:
bb_pan 2025-02-07 16:27:08 +08:00
parent d1e35d9352
commit 08c3874947
9 changed files with 172 additions and 17 deletions

14
package-lock.json generated
View File

@ -28,6 +28,7 @@
"pinia": "^2.1.7",
"pinia-plugin-persist": "^1.0.0",
"quill": "^2.0.3",
"sm-crypto": "^0.3.13",
"tinymce": "^7.6.0",
"vite-plugin-html": "^3.2.0",
"vite-plugin-zip-file": "^2.2.0",
@ -4456,6 +4457,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/sm-crypto": {
"version": "0.3.13",
"resolved": "https://registry.npmmirror.com/sm-crypto/-/sm-crypto-0.3.13.tgz",
"integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==",
"dependencies": {
"jsbn": "^1.1.0"
}
},
"node_modules/sm-crypto/node_modules/jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://repo.huaweicloud.com/repository/npm/source-map/-/source-map-0.6.1.tgz",

View File

@ -35,6 +35,7 @@
"pinia": "^2.1.7",
"pinia-plugin-persist": "^1.0.0",
"quill": "^2.0.3",
"sm-crypto": "^0.3.13",
"tinymce": "^7.6.0",
"vite-plugin-html": "^3.2.0",
"vite-plugin-zip-file": "^2.2.0",

View File

@ -6,6 +6,8 @@ import NProgress from 'nprogress'
import { ElMessage } from 'element-plus'
import { saveAs } from 'file-saver'
import router from '@/router'
import { tansParams } from '@/utils/bonus'
import { decryptWithSM4, encryptWithSM4, hashWithSM3AndSalt } from '@/utils/sm'
// const store = mainStore()
// const CancelToken = axios.CancelToken
@ -22,9 +24,28 @@ const service = axios.create({
timeout: 60000,
})
// 请求拦截
service.interceptors.request.use(
(config) => {
config.headers['Authorization'] = localStorage.getItem('tokenNew')
// 入参是否加密
config.headers['encryptRequest'] = 'true'
// 数据完整性校验
config.headers['checkIntegrity'] = 'true'
// 回参是否加密
config.headers['encryptResponse'] = 'true'
// 对请求数据进行加密
if (config.method === 'get' && config.params) {
let url = config.url + '?' + tansParams(config.params)
url = url.slice(0, -1)
config.params = {}
config.url = url
}
if (config.data) {
let data = typeof config.data === 'object' ? JSON.stringify(config.data) : config.data
config.data = encryptWithSM4(data+"|"+hashWithSM3AndSalt(data))
}
return config
},
(error) => {
@ -35,7 +56,9 @@ service.interceptors.request.use(
service.interceptors.response.use(
(res) => {
ElMessage.closeAll()
const { data } = res
// const { data } = res
const data = JSON.parse(decryptWithSM4(res.data))
// console.log('🚀 ~ data:', data)
if (data.code == '200') {
return data
} else if (data.code == '403') {

View File

@ -32,6 +32,7 @@ const activeLoginCompanyName = ref('')
const searchCheckVisible = ref(false)
import { storeToRefs } from 'pinia'
const { userInfo, token }: any = storeToRefs(store)
const tokenNew = localStorage.getItem('tokenNew')
if (roles?.length > 0) {
isAdmin.value = roles.some((e: any) => e.roleKey == 'admin')
}
@ -52,12 +53,13 @@ watch(userInfo, (newValue, oldCount) => {
})
}
})
watch(token, (newValue, oldCount) => {
if (newValue) {
getUserListData()
getBookCarDetailsData()
}
})
// watch(token, (newValue, oldCount) => {
// if (newValue) {
// getUserListData()
// getBookCarDetailsData()
// }
// })
// tokenNew
const setActiveCompanyName = () => {
// const companyList = userStore.companyList
@ -244,10 +246,14 @@ const onSelectRoles = (type: number) => {
const getBookCarDetailsData = async () => {
const res: any = await getBookCarDetailsApi()
console.log('🚀 ~ getBookCarDetailsData ~ res:', res)
let amountNum = 0
res.data.forEach((e: any) => {
amountNum = e.devInfoVoList.length + amountNum
})
if (res.data && res.data.length > 0) {
res.data.forEach((e: any) => {
amountNum = e.devInfoVoList.length + amountNum
console.log('🚀 ~ res.data.forEach ~ amountNum:', amountNum)
})
}
cart.SET_CART_NUM(amountNum)
}
const cartNum = computed(() => {
@ -372,9 +378,12 @@ const resetPhone = async () => {
})
}
// onMounted(() => {
// circleUrl.value = store.userInfo.avatar
// })
onMounted(() => {
if (tokenNew) {
getUserListData()
getBookCarDetailsData()
}
})
</script>
<template>

25
src/utils/bonus.ts Normal file
View File

@ -0,0 +1,25 @@
/**
*
* @param {*} params
*/
export function tansParams(params: any) {
let result = ''
for (const propName of Object.keys(params)) {
const value = params[propName]
var part = encodeURIComponent(propName) + '='
if (value !== null && value !== '' && typeof value !== 'undefined') {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
if (value[key] !== null && value[key] !== '' && typeof value[key] !== 'undefined') {
let params = propName + '[' + key + ']'
var subPart = encodeURIComponent(params) + '='
result += subPart + encodeURIComponent(value[key]) + '&'
}
}
} else {
result += part + encodeURIComponent(value) + '&'
}
}
}
return result
}

23
src/utils/configure.ts Normal file
View File

@ -0,0 +1,23 @@
// SM 配置
export const SM_CONFIG = {
SALT: '2cc0c5f9f1749f1632efa9f63e902323', // SM3 盐值16 字节)
SM4_KEY:"78d1295afa99449b99d6f83820e6965c", // SM4 对称加密密钥
SM4_SALT:"f555adf6c01d0ab0761e626a2dae34a2",
SM2_PUBLIC_KEY: 'your-public-key', // SM2 公钥
SM2_PRIVATE_KEY: 'your-private-key' // SM2 私钥
}
// AES 配置
export const AES_CONFIG = {
AES_KEY: 'zhgd@bonus@zhgd@bonus@1234567890', // AES key值
AES_IV: '1234567812345678' // AES 偏移量
}
export function generateUUID() {
// 使用当前时间戳和随机数生成一个 UUID
return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
const r = Math.random() * 16 | 0; // 生成随机数
const v = c === 'x' ? r : (r & 0x3 | 0x8); // 根据 UUID 规范生成相应的值
return v.toString(16); // 转换为十六进制
});
}

57
src/utils/sm.ts Normal file
View File

@ -0,0 +1,57 @@
// src/utils/encryption.js
import { sm2, sm3, sm4 } from 'sm-crypto'
// 配置项例如盐值、SM2 公私钥、SM4 密钥
import { SM_CONFIG } from './configure'
import SM4 from 'sm-crypto/src/sm4'
import { hexToArray } from 'sm-crypto/src/sm2/utils'
// SM3 哈希
export function hashSM3(text: any) {
// 对数据进行哈希计算
return sm3(text)
}
// 使用 SM3 进行哈希并加入盐值
export function hashWithSM3AndSalt(text: any) {
// 将文本和盐值拼接在一起
const textWithSalt = SM_CONFIG.SALT + text
// 使用 SM3 进行哈希
return hashSM3(textWithSalt)
}
// SM2 加密
export function encryptWithSM2(text: any) {
// SM2 公钥加密
return sm2.doEncrypt(text, SM_CONFIG.SM2_PUBLIC_KEY)
}
// SM2 解密
export function decryptWithSM2(encryptedText: any) {
// SM2 私钥解密
return sm2.doDecrypt(encryptedText, SM_CONFIG.SM2_PRIVATE_KEY)
}
/**
*
* @param {string} plainText
* @returns {string} Hex
*/
export function encryptWithSM4(plainText: any) {
return sm4.encrypt(plainText, SM_CONFIG.SM4_KEY, {
mode: 'cbc',
padding: 'pkcs#5',
iv: SM_CONFIG.SM4_SALT,
})
}
/**
*
* @param {string} cipherText
* @returns {string}
*/
export function decryptWithSM4(cipherText: any) {
return SM4.decrypt(cipherText, SM_CONFIG.SM4_KEY, {
mode: 'cbc',
padding: 'pkcs#5',
iv: SM_CONFIG.SM4_SALT,
})
}

View File

@ -36,12 +36,12 @@ const allList = [
{ title: '租赁订单', name: 'orderManagement', permission: ['2'] },
{ title: '收货地址管理', name: 'address-manage', permission: ['2'] },
{ title: '合同管理', name: 'contract-manage', permission: ['1'] },
{ title: '快捷消息设置', name: 'quickMessage', permission: ['1'] },
// { title: '', name: 'quickMessage', permission: ['1'] },
// { title: '', name: 'personalCenter', permission: ['1'] },
// { title: '', name: 'personalCenter', permission: ['2'] },
]
const rolesType = ref('承租方')
const rolesType = ref(localStorage.getItem('rolesTypeName') || '出租方')
const menuList: any = computed(() => {
if (rolesType.value == '承租方') return allList.filter((e) => e.permission.includes('2'))
if (rolesType.value == '出租方') return allList.filter((e) => e.permission.includes('1'))
@ -65,11 +65,13 @@ const onChange = (val: any) => {
router.push({
name: 'sourcingNeed',
})
localStorage.setItem('rolesTypeName', '承租方')
} else {
store.editcurrentMenuItem('goodsManagement')
router.push({
name: 'goodsManagement',
})
localStorage.setItem('rolesTypeName', '出租方')
}
}
onBeforeUnmount(() => {
@ -101,7 +103,7 @@ onBeforeUnmount(() => {
<el-menu
class="el-menu-vertical-demo"
@select="handleSelect"
:default-active="route.name"
:default-active="route && route.name ? route.name : ''"
>
<template v-for="(item, index) in menuList" :key="index">
<el-menu-item :index="item.name">

View File

@ -72,7 +72,8 @@ const statusList: any = [
]
const orderText = (status: any) => {
return statusList.filter((e: any) => e.id == status)[0].name
const statusItem = statusList.find((e: any) => e.id == status)
return statusItem ? statusItem.name : ''
}
const orderType = (status: any) => {
if (status == 1 || status == 2 || status == 3 || status == 5) return 'primary'