数据加密
This commit is contained in:
parent
ffd872a113
commit
889b4327bd
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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); // 转换为十六进制
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -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,
|
||||
})
|
||||
}
|
||||
Loading…
Reference in New Issue