加解密

This commit is contained in:
bb_pan 2025-07-21 15:31:49 +08:00
parent d9f7b944a7
commit 1609e6d9e2
9 changed files with 176 additions and 10 deletions

14
package-lock.json generated
View File

@ -30,6 +30,7 @@
"pinia-plugin-persistedstate": "^3.2.3",
"sass": "^1.32.13",
"sass-loader": "^16.0.3",
"sm-crypto": "^0.3.13",
"vue": "^3.5.13",
"vue-i18n": "^9.14.1"
},
@ -9462,6 +9463,11 @@
"js-yaml": "bin/js-yaml.js"
}
},
"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/jsdom": {
"version": "16.7.0",
"resolved": "https://registry.npmmirror.com/jsdom/-/jsdom-16.7.0.tgz",
@ -11815,6 +11821,14 @@
"node": ">=8"
}
},
"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/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmmirror.com/source-map/-/source-map-0.6.1.tgz",

View File

@ -64,6 +64,7 @@
"pinia-plugin-persistedstate": "^3.2.3",
"sass": "^1.32.13",
"sass-loader": "^16.0.3",
"sm-crypto": "^0.3.13",
"vue": "^3.5.13",
"vue-i18n": "^9.14.1"
},

View File

@ -21,7 +21,7 @@
<script setup>
import { onMounted, reactive, ref } from 'vue'
import { appLoginAPI, getUserInfoAPI, iwsLoginAPI } from '@/services/index.js'
import { appLoginAPI, getUserInfoAPI, iwsLoginAPI, getConfigApi } from '@/services/index.js'
import { useMemberStore } from '@/stores'
const memberStore = useMemberStore()
const origin = window.location.href
@ -37,12 +37,13 @@ const loginForm = reactive({
})
onMounted(async () => {
console.log('🚀 ~ onMounted ~ origin:', origin)
// console.log('🚀 ~ onMounted ~ origin:', origin)
// uni.showToast({
// title: origin,
// icon: 'none',
// duration: 5000,
// })
getConfig()
if (origin.indexOf('ticket') != -1) {
try {
uni.showLoading({ title: '登录中' })
@ -109,6 +110,14 @@ const onHandleLogin = async () => {
console.log('🚀 ~ onHandleLogin ~ error:', error)
}
}
const getConfig = async () => {
try {
const res = await getConfigApi()
uni.setStorageSync('systemConfig', res.data)
} catch (error) {
console.log('🚀 ~ getConfig ~ error:', error)
}
}
</script>
<style lang="scss" scoped>

View File

@ -135,8 +135,6 @@ import { onShow,onLoad } from '@dcloudio/uni-app'
const urlPermissions = ref([])
onShow((options) => {
urlPermissions.value = uni.getStorageSync('urlPermissions')
console.log("yyyyyyy",urlPermissions.value)
})

View File

@ -37,4 +37,12 @@ export const iwsLoginAPI = (data) => {
url: '/auth/iwsLogin',
data,
})
}
// 获取系统配置
export const getConfigApi = () => {
return http({
method: 'GET',
url: '/auth/getConfig',
})
}

23
src/utils/configure.js 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); // 转换为十六进制
});
}

View File

@ -1,4 +1,9 @@
import { useMemberStore } from '@/stores'
import { decryptWithSM4, encryptWithSM4, hashWithSM3AndSalt } from './sm'
const systemConfig = uni.getStorageSync('systemConfig') || {
requestConfig: { encryptRequest: false, checkIntegrity: false, encryptResponse: false },
}
/**
* 添加拦截器
@ -8,19 +13,16 @@ import { useMemberStore } from '@/stores'
const ENV = process.env.NODE_ENV
// export const baseURL = ENV === 'development' ? 'http://192.168.0.244:18580' : 'http://192.168.0.244:18580'//测试
// export const baseURL = ENV === 'development' ? 'http://sgwpdm.ah.sgcc.com.cn/iws/jiju-api/' : 'http://sgwpdm.ah.sgcc.com.cn/iws/jiju-api/'//生产
export const baseURL = ENV === 'development' ? '/api' : '/iws/jiju-api'; // 宏源服务
// export const baseURL = ENV === 'development' ? 'http://192.168.0.234:18080' : '***'
export const baseURL = ENV === 'development' ? '/api' : '/iws/jiju-api' // 宏源服务
// export const baseURL = ENV === 'development' ? 'http://192.168.0.234:18080' : '***'
// export const baseURL = ENV === 'development' ? 'http://192.168.1.114:18080' : 'http://192.168.1.117:18080'//马
// export const baseURL = ENV === 'development' ? '/api' : '***'
// **********OCR识别为NVUE文件页面请求URL需要同步配置**********
/**
* httpInterceptor 分别拦截 request uploadFile 请求
*/
*/
// 添加请求拦截
const httpInterceptor = {
invoke(options) {
@ -38,6 +40,20 @@ const httpInterceptor = {
...options.header,
}
const header = options.header || {}
const { encryptRequest = true, checkIntegrity = true, encryptResponse = true } = header
//入参加密
options.header['encryptRequest'] =
systemConfig.requestConfig.encryptRequest && encryptRequest ? 'true' : 'false'
// 数据完整性校验
options.header['checkIntegrity'] =
systemConfig.requestConfig.checkIntegrity && checkIntegrity ? 'true' : 'false'
//回参是否加密
options.header['encryptResponse'] =
systemConfig.requestConfig.encryptResponse && encryptResponse ? 'true' : 'false'
// console.log('🚀 ~ invoke ~ options:', options)
// 4. 增加 token 请求头标识
const memberStore = useMemberStore()
const token = memberStore.token
@ -45,6 +61,21 @@ const httpInterceptor = {
if (token) {
options.header.Authorization = token
}
// console.log('🚀 ~ invoke ~ 请求拦截:', options)
if (options.method === 'POST' || options.method === 'PUT') {
options.header['content-type'] = 'application/json;charset=utf-8;'
let contentType = options.header['content-type']
let data =
typeof options.data === 'object' ? JSON.stringify(options.data) : options.data
if (contentType.includes('application/json') && typeof data !== 'undefined') {
// 加密数据
if (systemConfig.requestConfig.encryptRequest && encryptRequest) {
console.log('加密后-->', hashWithSM3AndSalt(data))
options.data = encryptWithSM4(data + '|' + hashWithSM3AndSalt(data))
}
}
}
},
}
@ -57,7 +88,11 @@ export const http = (options) => {
uni.request({
...options,
success(res) {
// console.log('🚀 ~ 响应拦截 ~ res:', res)
try {
if (res.header.encryptresponse == 'true' && res.statusCode === 200) {
res.data = JSON.parse(decryptWithSM4(res.data))
}
// 1. 判断是否请求成功
if (res.statusCode >= 200 && res.statusCode < 300) {
if (res.data && res.data.code >= 200 && res.data.code < 300) {

30
src/utils/jsencrypt.js Normal file
View File

@ -0,0 +1,30 @@
import JSEncrypt from 'jsencrypt/bin/jsencrypt.min'
// 密钥对生成 http://web.chacuo.net/netrsakeypair
const publicKey = 'MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdH\n' +
'nzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ=='
const privateKey = 'MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAqhHyZfSsYourNxaY\n' +
'7Nt+PrgrxkiA50efORdI5U5lsW79MmFnusUA355oaSXcLhu5xxB38SMSyP2KvuKN\n' +
'PuH3owIDAQABAkAfoiLyL+Z4lf4Myxk6xUDgLaWGximj20CUf+5BKKnlrK+Ed8gA\n' +
'kM0HqoTt2UZwA5E2MzS4EI2gjfQhz5X28uqxAiEA3wNFxfrCZlSZHb0gn2zDpWow\n' +
'cSxQAgiCstxGUoOqlW8CIQDDOerGKH5OmCJ4Z21v+F25WaHYPxCFMvwxpcw99Ecv\n' +
'DQIgIdhDTIqD2jfYjPTY8Jj3EDGPbH2HHuffvflECt3Ek60CIQCFRlCkHpi7hthh\n' +
'YhovyloRYsM+IS9h/0BzlEAuO0ktMQIgSPT3aFAgJYwKpqRYKlLDVcflZFCKY7u3\n' +
'UP8iWi1Qw0Y='
// 加密
export function encrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPublicKey(publicKey) // 设置公钥
return encryptor.encrypt(txt) // 对数据进行加密
}
// 解密
export function decrypt(txt) {
const encryptor = new JSEncrypt()
encryptor.setPrivateKey(privateKey) // 设置私钥
return encryptor.decrypt(txt) // 对数据进行解密
}

48
src/utils/sm.js Normal file
View File

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