HoRain云--如何在Vue中实现数据的加密和解密
在Vue中实现数据加密解密需要结合现代浏览器API或第三方加密库,以下是多种实现方案及其应用场景:
·
🎬 HoRain 云小助手:个人主页
⛺️生活的理想,就是为了理想的生活!
⛳️ 推荐
前些天发现了一个超棒的服务器购买网站,性价比超高,大内存超划算!忍不住分享一下给大家。点击跳转到网站。
目录
一、加密基础原则
- 前端加密不能替代HTTPS(仅作为额外保护层)
- 避免硬编码密钥(可通过服务端动态获取)
- 敏感数据必须服务端二次加密
- 优先使用现代加密标准(AES-GCM、RSA-OAEP等)
二、使用Web Crypto API(原生方案)
1. 创建加密工具类
// utils/crypto.js
const encoder = new TextEncoder()
const decoder = new TextDecoder()
export async function generateKey() {
return window.crypto.subtle.generateKey(
{ name: "AES-GCM", length: 256 },
true, // 是否可导出
["encrypt", "decrypt"]
)
}
export async function encryptData(plainText, key) {
const iv = window.crypto.getRandomValues(new Uint8Array(12))
const encoded = encoder.encode(plainText)
const cipherText = await window.crypto.subtle.encrypt(
{ name: "AES-GCM", iv },
key,
encoded
)
return { iv, cipherText }
}
export async function decryptData({ iv, cipherText }, key) {
try {
const decrypted = await window.crypto.subtle.decrypt(
{ name: "AES-GCM", iv },
key,
cipherText
)
return decoder.decode(decrypted)
} catch (error) {
console.error("解密失败:", error)
return null
}
}
2. 在组件中使用
<script setup>
import { ref } from 'vue'
import { generateKey, encryptData, decryptData } from '@/utils/crypto'
const key = ref(null)
const secretMessage = ref('')
const encryptedData = ref(null)
// 生成密钥
generateKey().then(k => key.value = k)
const handleEncrypt = async () => {
if (!key.value) return
encryptedData.value = await encryptData(secretMessage.value, key.value)
}
const handleDecrypt = async () => {
if (!encryptedData.value) return
const decrypted = await decryptData(encryptedData.value, key.value)
console.log('解密结果:', decrypted)
}
</script>
三、集成CryptoJS(兼容旧浏览器)
1. 安装库
npm install crypto-js
2. 封装加密工具
// utils/crypto-utils.js
import CryptoJS from 'crypto-js'
const SECRET_KEY = import.meta.env.VITE_CRYPTO_KEY // 从环境变量获取
export const encrypt = (text) => {
const encrypted = CryptoJS.AES.encrypt(
text,
CryptoJS.enc.Utf8.parse(SECRET_KEY),
{
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv: CryptoJS.enc.Utf8.parse(SECRET_KEY.slice(0, 16))
}
)
return encrypted.toString()
}
export const decrypt = (cipherText) => {
const decrypted = CryptoJS.AES.decrypt(
cipherText,
CryptoJS.enc.Utf8.parse(SECRET_KEY),
{
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7,
iv: CryptoJS.enc.Utf8.parse(SECRET_KEY.slice(0, 16))
}
)
return decrypted.toString(CryptoJS.enc.Utf8)
}
四、结合状态管理加密
1. Pinia存储加密示例
// stores/user.js
import { defineStore } from 'pinia'
import { encrypt, decrypt } from '@/utils/crypto-utils'
export const useUserStore = defineStore('user', {
state: () => ({
_encryptedToken: null, // 加密后的token
publicInfo: {}
}),
getters: {
token: (state) => {
return state._encryptedToken ? decrypt(state._encryptedToken) : null
}
},
actions: {
setToken(rawToken) {
this._encryptedToken = encrypt(rawToken)
}
},
persist: {
paths: ['_encryptedToken', 'publicInfo']
}
})
2. 安全使用方式
<script setup>
import { useUserStore } from '@/stores/user'
const userStore = useUserStore()
// 存储时自动加密
const login = async () => {
const res = await fetch('/api/login')
const { token } = await res.json()
userStore.setToken(token) // 自动加密存储
}
// 读取时自动解密
const checkAuth = () => {
console.log('当前Token:', userStore.token) // 透明解密
}
</script>
五、混合加密方案(非对称+对称)
// 结合RSA和AES
async function hybridEncrypt(plainText, publicKey) {
// 1. 生成临时AES密钥
const aesKey = await generateAESKey()
// 2. 用AES加密数据
const { cipherText, iv } = await aesEncrypt(plainText, aesKey)
// 3. 用RSA加密AES密钥
const encryptedKey = await rsaEncrypt(aesKey, publicKey)
return { encryptedKey, cipherText, iv }
}
async function hybridDecrypt({ encryptedKey, cipherText, iv }, privateKey) {
// 1. 解密AES密钥
const aesKey = await rsaDecrypt(encryptedKey, privateKey)
// 2. 解密数据
return aesDecrypt({ cipherText, iv }, aesKey)
}
六、安全增强措施
-
动态密钥管理
// 每次页面加载从服务端获取密钥 async function getEncryptionKey() { const res = await fetch('/api/encryption-key') return res.json().key }
-
内存密钥保护
const volatileKey = new WeakMap() // 内存中不保留密钥副本 function storeKey(key) { const obj = {} volatileKey.set(obj, key) return obj }
-
加密数据验证
function encryptWithHMAC(text, key) { const cipherText = encrypt(text, key) const hmac = CryptoJS.HmacSHA256(cipherText, key).toString() return `${hmac}$${cipherText}` }
七、不同场景选型建议
场景 | 推荐方案 | 优点 |
---|---|---|
现代浏览器应用 | Web Crypto API + Pinia | 原生支持,性能最优 |
兼容旧浏览器 | CryptoJS + Vuex | 兼容性好,API简单 |
高安全要求系统 | 混合加密 + 服务端密钥管理 | 防御中间人攻击 |
临时数据保护 | 内存加密 + Web Workers | 数据不落盘 |
八、注意事项
-
不要加密以下内容:
- 需要服务端处理的原始数据
- 前端展示的明文信息
- 高频更新的状态数据
-
性能监控:
// 加密性能测试 console.time('AES加密耗时') const encrypted = encrypt(largeData) console.timeEnd('AES加密耗时')
-
错误处理:
try { const data = decrypt(encryptedText) } catch (err) { Sentry.captureException(err) showToast('数据损坏,请重新登录') }
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄
💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍
🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙
更多推荐
所有评论(0)