1. 代码
使用的库
cryptojs
/*
import.meta.env.VITE_KEY: 自定义密钥
*/
// 加密 - 加密单个字段
export const addPassword = (str: string) => {
const message = cryptojs.enc.Utf8.parse(str)
const secretPassphrase = cryptojs.enc.Utf8.parse(import.meta.env.VITE_KEY)
const iv = cryptojs.enc.Utf8.parse(import.meta.env.VITE_KEY)
return cryptojs.AES.encrypt(message, secretPassphrase, {
mode: cryptojs.mode.CBC,
padding: cryptojs.pad.Pkcs7,
iv
}).toString()
}
// 解密 - 解密单个字段
export const passPassword = (passStr: string) => {
const secretPassphrase = cryptojs.enc.Utf8.parse(import.meta.env.VITE_KEY)
const iv = cryptojs.enc.Utf8.parse(import.meta.env.VITE_KEY)
return cryptojs.AES.decrypt(passStr, secretPassphrase, {
mode: cryptojs.mode.CBC,
padding: cryptojs.pad.Pkcs7,
iv
}).toString(cryptojs.enc.Utf8)
}
// 加密 - 加密参数对象
export const addPasswordParams = (obj: any) => {
const vObject: { [key: string]: any } = {}
for (let key in obj) {
const k = addPassword(key)
if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
vObject[k] = addPasswordParams(obj[key])
} else if (Array.isArray(obj[key])) {
vObject[k] = obj[key].map((item: any) => {
if (item instanceof Object) {
return addPasswordParams(item)
}
return addPassword(item)
})
} else {
vObject[k] = addPassword(obj[key])
}
}
return vObject
}
// 解密 - 解密参数对象
export const passPasswordParams = (obj: any) => {
const vObject: { [key: string]: any } = {}
for (let key in obj) {
const k = passPassword(key)
if (Object.prototype.toString.call(obj[key]) === '[object Object]') {
vObject[k] = passPasswordParams(obj[key])
} else if (Array.isArray(obj[key])) {
vObject[k] = obj[key].map((item: any) => {
if (item instanceof Object) {
return passPasswordParams(item)
}
return passPassword(item)
})
} else {
vObject[k] = passPassword(obj[key])
}
}
return vObject
}
2. 前端
参考 web-fetch封装, 添加
props.body = JSON.stringify(addPasswordParams(JSON.parse(props.body as string)))
// 请求
async request(url: string, props: RequestInit & { headers?: controlType }) {
props.body = JSON.stringify(addPasswordParams(JSON.parse(props.body as string)))
const newURL = this.joinUrl(url)
this.beforeFetch(newURL, props)
try {
let response: any
if (props.headers?.file === 'true') {
response = await (await fetch(newURL, props)).blob()
} else {
response = await (await fetch(newURL, props)).json()
}
return this.afterFetch(response, props)
} catch (e: any) {
return {
status: 1000,
message: e.message
}
}
}
3. nodeJs
这里的相关函数的 key
改为了函数参数传入,其他不变。
在前置中间件中添加
req.params = passPasswordParams(paramSecretKey, req.params)
req.body = passPasswordParams(paramSecretKey, req.body)
req.query = passPasswordParams(paramSecretKey, req.query)
前置中间件示例:
// 前置中间件
app.use((req, res, next) => {
let checkPermission = false
// 校验一下有没有调用权限
checkPermission = checkHeaders(req.headers)
if (!checkPermission) {
res.send({
message: '没有调用权限',
showMessage: true,
messageType: messageTypes.error,
data: {},
status: 401
})
return
}
// 数据解析
req.params = passPasswordParams(paramSecretKey, req.params)
req.body = passPasswordParams(paramSecretKey, req.body)
req.query = passPasswordParams(paramSecretKey, req.query)
// 错误中间件
res.error = (message, showMessage = true, messageType = messageTypes.error, status = 500) => {
res.send({
message,
showMessage,
messageType,
data: {},
status
})
return
}
// 挂载 加密 模块 生成密文
res.bcryptjs = bcryptjs
// 挂载 签名 秘钥 token密钥
res.tokenSecretKey = tokenSecretKey
// 挂载 签名 秘钥 token密钥
res.dataSecretKey = dataSecretKey
// 挂载 签名 秘钥 token密钥
res.paramSecretKey = paramSecretKey
// 挂载 签名 模块 生成token
res.jwt = jwt
// 挂载 解析 模块 解析token
res.expressjwt = expressjwt
// 加密参数 - 单个
res.addPasswordParam = (str) => addPasswordParam(paramSecretKey, str)
// 加密参数 - 对象
res.addPasswordParams = (obj) => addPasswordParams(paramSecretKey, obj)
// 解密参数 - 单个
res.passPasswordParam = (str) => passPasswordParam(paramSecretKey, str)
// 解密参数 - 对象
res.passPasswordParams = (obj) => passPasswordParams(paramSecretKey, obj)
next()
})
4. 效果
// 加密
const add = addPasswordParams({
pageNumber: 1,
pageSize: 10,
tabName: 'today'
})
// add 的值:
{
"A5UU4ICRCMMn06IvrGtLww==": "9qlNjjqyprYHxzKf0IG8qg==",
"AOSS2snSNFdcJFziGdxatQ==": "r7oub6PUU0yHRPnXqeDXOw==",
"199edTursmIsrF9az/hSwA==": "9qlNjjqyprYHxzKf0IG8qg=="
}
// 解密
const pass = passPasswordParams({
"A5UU4ICRCMMn06IvrGtLww==": "9qlNjjqyprYHxzKf0IG8qg==",
"AOSS2snSNFdcJFziGdxatQ==": "r7oub6PUU0yHRPnXqeDXOw==",
"199edTursmIsrF9az/hSwA==": "9qlNjjqyprYHxzKf0IG8qg=="
})
// pass 的值:
{
pageNumber: '1',
pageSize: '10',
tabName: 'today'
}
注意上面解密后 数字变成了字符串, 需要做处理