Pinia状态持久化需通过插件实现加密,核心是序列化前加密、反序列化后解密;推荐crypto-js(AES-CBC+IV)用于中低敏感场景,Web Crypto API(AES-GCM)用于高安全需求;应分级存储、字段过滤、避免密钥硬编码,并注意SSR/跨平台兼容性。

Pinia 状态持久化本身不带加密能力,加密必须通过插件机制在序列化/反序列化环节主动介入。核心思路是:状态写入存储前加密,读取时解密还原,整个过程对业务 Store 透明。
用 crypto-js 实现 AES 加密插件
这是最常用、上手最快的方案,适合中低敏感度场景(如用户偏好、表单草稿):
- 安装依赖:
npm install crypto-js - 密钥建议使用 16/24/32 字节 UTF-8 字符串(如
'a0b1c2d3e4f5g6h7'),避免硬编码,生产环境应从环境变量或登录后动态获取 - 插件中统一处理加解密逻辑:初始化时读取并尝试解密;状态变更后立即加密写入
localStorage - 推荐使用 CBC 模式 + PKCS7 填充,并配 IV(初始向量)提升安全性,比简单 ECB 更抗重放攻击
对接 Web Crypto API 做原生高性能加密
适用于高安全要求或大数据量场景(如金融类 token、加密凭证),性能优于 crypto-js,且无需引入第三方库:
- 利用浏览器原生
window.crypto.subtle调用AES-GCM,支持认证加密(AEAD),可验证数据完整性 - 密钥需通过
importKey()导入,不能直接传字符串;IV 每次加密应随机生成并随密文一并存储(如拼接为 Base64) - 注意兼容性:IE 不支持,但现代主流浏览器(Chrome 91+、Firefox 88+、Safari 15.4+)均已完善支持
- 异步 API 天然适配 Pinia 的
$subscribe,不会阻塞主线程
敏感数据分级与存储隔离策略
不是所有状态都值得加密,混合策略更合理高效:
- 高敏字段(如 access_token、refresh_token、身份证号)建议单独抽离到专用 store(如
useAuthStore),仅对该 store 启用加密插件 - 中低敏数据(如主题色、语言、折叠菜单状态)可用
pinia-plugin-persistedstate配合普通 localStorage - 临时数据(如搜索关键词、表单输入中的未提交内容)可存 sessionStorage 或完全不持久化
- 避免将整个
store.$state无差别加密——先做字段过滤,再加密精简后的对象
跨平台与 SSR 兼容要点
在 uni-app 或服务端渲染项目中,加密插件需规避环境限制:
- SSR 场景下,
window和加密 API 不存在,插件需包裹if (typeof window !== 'undefined')判断,或使用onMounted延迟到客户端执行 - uni-app 中优先用
pinia-plugin-persist-uni,它已内置平台适配逻辑(自动识别 h5/mp/app 并调用对应存储 API) - 小程序环境不支持 Web Crypto,此时 crypto-js 是更稳妥的选择,但要注意体积和性能影响
- 加密密钥绝不写死在前端代码中,可通过登录成功后由后端下发,或结合设备指纹生成派生密钥

















