数据加密

This commit is contained in:
bb_pan 2025-02-13 15:42:46 +08:00
parent ffd872a113
commit 889b4327bd
5 changed files with 215 additions and 30 deletions

View File

@ -34,6 +34,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

@ -3,9 +3,11 @@
import axios from 'axios'
import NProgress from 'nprogress'
// import { mainStore } from 'store/main'
import { ElMessage } from "element-plus";
import { ElMessage } from 'element-plus'
import { saveAs } from 'file-saver'
import router from "@/router"
import router from '@/router'
import { tansParams } from '@/utils/bonus'
import { decryptWithSM4, encryptWithSM4, hashWithSM3AndSalt } from '@/utils/sm'
// const store = mainStore()
// const CancelToken = axios.CancelToken
@ -15,53 +17,110 @@ const VITE_token = import.meta.env.VITE_token
const VITE_LocalFlag = import.meta.env.VITE_LocalFlag
const VITE_ENV = import.meta.env.VITE_ENV
const iwsData: any = sessionStorage.getItem('data') || null
const service = axios.create({
baseURL: baseUrl,
timeout: 60000
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) => {
return error
}
},
)
// 响应拦截
service.interceptors.response.use(
(res) => {
ElMessage.closeAll()
const { data } = res
let data: any = null
if (res.headers.encryptresponse && !res.data.hasOwnProperty('code')) {
data = JSON.parse(decryptWithSM4(res.data))
} else {
data = res.data
}
// console.log('🚀 ~ 响应-data:', data)
if (data.code == '200') {
return data
} else if (data.code == '403') {
ElMessage.error('请重新登录')
router.push('/login')
// 根据环境变量 VITE_API_URL 判断是否是本地开发环境
if (import.meta.env.VITE_API_URL == '/proxyApi') {
router.push('/login')
} else {
setTimeout(() => {
window.location.replace(
'http://sgwpdm.ah.sgcc.com.cn/iws/cas/login?appId=3874dcb953f184dc75450e33d6d6d4fa&service=http://sgwpdm.ah.sgcc.com.cn/iws/mall-view/',
)
}, 500)
}
} else if (data.code == '401') {
ElMessage.error(data.msg)
router.push('/login')
ElMessage.error('请重新登录')
if (import.meta.env.VITE_API_URL == '/proxyApi') {
router.push('/login')
} else {
setTimeout(() => {
window.location.replace(
'http://sgwpdm.ah.sgcc.com.cn/iws/cas/login?appId=3874dcb953f184dc75450e33d6d6d4fa&service=http://sgwpdm.ah.sgcc.com.cn/iws/mall-view/',
)
}, 500)
}
} else if (data.code == '500') {
ElMessage({
type: 'error',
message: data.msg,
duration: 1000,
})
}
else {
} else {
return data
}
},
(error) => {
// ElMessage.error('请求失败')
// console.log('error-异常', error)
}
},
)
export function get(url: string, params: any) {
// if (iwsData) {
// service
// .get(
// `http://sgwpdm.ah.sgcc.com.cn/iws/cas/api/validate/sk?sessionKey=${iwsData.sessionKey}`,
// )
// .then((res: any) => {
// console.log(res, '请求结果')
// if (res.code != 200) {
// window.location.replace(
// 'http://sgwpdm.ah.sgcc.com.cn/iws/cas/login?appId=3874dcb953f184dc75450e33d6d6d4fa&service=http://sgwpdm.ah.sgcc.com.cn/iws/mall-view/',
// )
// }
// return false
// })
// }
return new Promise((resolve, reject) => {
// NProgress.start()
service
@ -81,11 +140,28 @@ export function get(url: string, params: any) {
})
}
export function post(url: string, params: any) {
// if (iwsData) {
// service
// .get(
// `http://sgwpdm.ah.sgcc.com.cn/iws/cas/api/validate/sk?sessionKey=${iwsData.sessionKey}`,
// )
// .then((res: any) => {
// console.log(res, '请求结果')
// if (res.code != 200) {
// window.location.replace(
// 'http://sgwpdm.ah.sgcc.com.cn/iws/cas/login?appId=3874dcb953f184dc75450e33d6d6d4fa&service=http://sgwpdm.ah.sgcc.com.cn/iws/mall-view/',
// )
// }
// return false
// })
// }
return new Promise((resolve, reject) => {
// NProgress.start()
service
.post(url, params, {
headers: { 'Content-Type': 'application/json; charset=utf-8' }
headers: { 'Content-Type': 'application/json; charset=utf-8' },
})
.then((res: any) => {
NProgress.done()
@ -112,7 +188,7 @@ export function upload(url: string, params: any) {
NProgress.start()
service
.post(url, formData, {
headers: { 'Content-Type': 'multipart/form-data' }
headers: { 'Content-Type': 'multipart/form-data' },
})
.then((res: any) => {
NProgress.done()
@ -130,38 +206,41 @@ export function upload(url: string, params: any) {
}
export function download(url: string, params: any, fileName: string = 'downloaded_file') {
return new Promise((resolve, reject) => {
NProgress.start(); // 开始进度条
NProgress.start() // 开始进度条
service
.post(url, params, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
'Content-Type': 'application/x-www-form-urlencoded',
},
responseType: 'blob' // 请求返回数据类型为 Blob二进制流
responseType: 'blob', // 请求返回数据类型为 Blob二进制流
})
.then((res: any) => {
NProgress.done(); // 结束进度条
NProgress.done() // 结束进度条
// 判断返回的内容类型是否是 Blob
const contentType = res.headers['content-type'] || '';
if (!contentType.includes('application/octet-stream') && !contentType.includes('application/pdf')) {
reject('文件类型不正确');
return;
const contentType = res.headers['content-type'] || ''
if (
!contentType.includes('application/octet-stream') &&
!contentType.includes('application/pdf')
) {
reject('文件类型不正确')
return
}
// 处理文件下载
const blob = new Blob([res.data], { type: contentType });
const blob = new Blob([res.data], { type: contentType })
// 使用 file-saver 保存文件
saveAs(blob, fileName);
saveAs(blob, fileName)
resolve('文件下载成功');
resolve('文件下载成功')
})
.catch((err) => {
NProgress.done(); // 结束进度条
reject(err?.data || '下载失败');
});
});
NProgress.done() // 结束进度条
reject(err?.data || '下载失败')
})
})
}
export function put(url: string, params: any) {
@ -169,7 +248,7 @@ export function put(url: string, params: any) {
NProgress.start()
service
.put(url, params, {
headers: { 'Content-Type': 'application/json; charset=utf-8' }
headers: { 'Content-Type': 'application/json; charset=utf-8' },
})
.then((res: any) => {
NProgress.done()

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,
})
}