加密和解密函数应用到Pinia状态管理的具体步骤是什么?

简介: 加密和解密函数应用到Pinia状态管理的具体步骤是什么?

将加密和解密函数应用到 Pinia 状态管理的核心是通过 Pinia 插件实现自动化加解密,让状态在本地存储时加密、读取时解密,且对业务代码无侵入。以下是分7步的具体落地步骤,每一步都包含可直接复用的代码和关键说明:

整体流程概览

graph TD
    A[环境准备] --> B[编写加解密工具函数]
    B --> C[开发Pinia加密插件]
    C --> D[配置Pinia并注册插件]
    D --> E[定义加密的Store]
    E --> F[组件中使用Store]
    F --> G[登出清理加密数据]

具体步骤(附代码+说明)

步骤1:环境准备(安装核心依赖)

首先安装 Pinia(状态管理)和 crypto-js(加解密算法),这是实现功能的基础:

# npm 安装
npm install pinia crypto-js
# yarn 安装
yarn add pinia crypto-js
# pnpm 安装
pnpm add pinia crypto-js

步骤2:编写加密解密工具函数(封装可复用逻辑)

创建独立的工具文件,封装 AES 加解密逻辑(核心函数,可全局复用):

// src/utils/crypto.js
import CryptoJS from 'crypto-js';

// 🔥 生产环境:密钥/IV必须从后端动态获取(登录后返回),切勿硬编码!
// 示例密钥(AES要求16/24/32字节,IV固定16字节)
let SECRET_KEY = CryptoJS.enc.Utf8.parse('temp-16byte-key!!'); // 临时密钥
let IV = CryptoJS.enc.Utf8.parse('temp-16byte-iv__'); // 临时初始向量

// 动态更新密钥(登录后调用,替换临时密钥)
export const updateCryptoKey = (newKey, newIV) => {
   
  SECRET_KEY = CryptoJS.enc.Utf8.parse(newKey);
  IV = CryptoJS.enc.Utf8.parse(newIV);
};

// 加密函数:任意数据 → 加密后的字符串
export const encrypt = (data) => {
   
  if (!data) return '';
  try {
   
    // 统一转为JSON字符串(支持对象/数组类型)
    const dataStr = typeof data === 'string' ? data : JSON.stringify(data);
    // AES-CBC模式加密(更安全)
    return CryptoJS.AES.encrypt(dataStr, SECRET_KEY, {
   
      iv: IV,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    }).toString();
  } catch (err) {
   
    console.error('加密失败:', err);
    return '';
  }
};

// 解密函数:加密字符串 → 原始数据(还原类型)
export const decrypt = (encryptedStr) => {
   
  if (!encryptedStr) return null;
  try {
   
    const decryptedBytes = CryptoJS.AES.decrypt(encryptedStr, SECRET_KEY, {
   
      iv: IV,
      mode: CryptoJS.mode.CBC,
      padding: CryptoJS.pad.Pkcs7
    });
    const decryptedStr = decryptedBytes.toString(CryptoJS.enc.Utf8);
    // 尝试还原为JSON对象(原始是对象则解析,否则返回字符串)
    return decryptedStr ? JSON.parse(decryptedStr) : null;
  } catch (err) {
   
    console.error('解密失败:', err);
    return null;
  }
};

步骤3:开发 Pinia 加密插件(核心:自动化加解密)

创建 Pinia 插件,实现「初始化解密加载状态 + 状态变化加密存储」的自动化逻辑:

// src/plugins/piniaEncrypt.js
import {
    encrypt, decrypt } from '@/utils/crypto';

/**
 * 创建Pinia加密插件
 * @param {Object} options 配置项
 * @param {Storage} options.storage 存储方式(localStorage/sessionStorage)
 * @param {string[]} options.include 需要加密的Store名称(空则全部加密)
 */
export const createEncryptPlugin = (options = {
   }) => {
   
  const {
    storage = localStorage, include = [] } = options;

  // 插件核心逻辑:每个Store初始化时执行
  return (context) => {
   
    const {
    store } = context;
    const storeId = store.$id; // 当前Store的唯一标识(如user/settings)

    // 只对指定Store加密(按需加密,减少性能损耗)
    const needEncrypt = include.length === 0 || include.includes(storeId);
    if (!needEncrypt) return;

    // 1. 初始化:从本地存储读取加密数据 → 解密 → 同步到Store
    const loadDecryptedState = () => {
   
      const encryptedData = storage.getItem(`pinia_${
     storeId}`);
      if (encryptedData) {
   
        const decryptedData = decrypt(encryptedData);
        if (decryptedData) {
   
          store.$patch(decryptedData); // 合并解密后的数据到状态
        }
      }
    };

    // 2. 状态变化时:加密 → 存储到本地(防抖避免频繁操作)
    const saveEncryptedState = () => {
   
      const currentState = store.$state; // 获取当前Store的完整状态
      const encryptedData = encrypt(currentState);
      storage.setItem(`pinia_${
     storeId}`, encryptedData);
    };

    // 初始化加载解密数据
    loadDecryptedState();

    // 监听Store状态变化(防抖:100ms内多次变化只执行一次)
    let debounceTimer;
    store.$subscribe(() => {
   
      clearTimeout(debounceTimer);
      debounceTimer = setTimeout(saveEncryptedState, 100);
    });

    // 3. 给Store扩展手动方法(可选)
    store.$encryptSave = saveEncryptedState; // 手动触发加密存储
    store.$clearEncryptedStorage = () => {
    // 手动清除加密数据
      storage.removeItem(`pinia_${
     storeId}`);
    };
  };
};

步骤4:配置 Pinia 并注册加密插件

在 Pinia 初始化文件中注册插件,指定加密规则(如只加密userStore):

// src/store/index.js
import {
    createPinia } from 'pinia';
import {
    createEncryptPlugin } from '@/plugins/piniaEncrypt';

// 创建Pinia实例
const pinia = createPinia();

// 注册加密插件:按需加密(只加密user Store)
pinia.use(createEncryptPlugin({
   
  storage: localStorage, // 可选:sessionStorage(会话级存储)
  include: ['user'] // 指定需要加密的Store名称
}));

export default pinia;

步骤5:定义需要加密的 Pinia Store

创建普通的 Store(无需关心加密逻辑,插件自动处理):

// src/store/user.js
import {
    defineStore } from 'pinia';

// 定义Store(id必须和插件中include的名称一致:user)
export const useUserStore = defineStore('user', {
   
  state: () => ({
   
    token: '', // 敏感:登录令牌
    userInfo: {
    // 敏感:用户信息
      id: '',
      name: '',
      phone: ''
    }
  }),
  actions: {
   
    // 登录:更新状态(插件自动加密存储)
    login(data) {
   
      this.token = data.token;
      this.userInfo = data.userInfo;
    },
    // 登出:重置状态 + 清除加密存储
    logout() {
   
      this.$reset(); // 重置Store状态
      this.$clearEncryptedStorage(); // 清除本地加密数据
    }
  }
});

步骤6:在组件中使用 Store(业务无感知)

组件中正常使用 Store,加密/解密由插件自动完成,无需额外操作:

<!-- src/views/Login.vue -->
<template>
  <div>
    <button @click="handleLogin">登录</button>
    <button @click="handleLogout">登出</button>
  </div>
</template>

<script setup>
import { useUserStore } from '@/store/user';
import { updateCryptoKey } from '@/utils/crypto';
// 模拟登录接口
import { loginApi } from '@/api/user';

const userStore = useUserStore();

// 登录逻辑
const handleLogin = async () => {
  // 1. 调用登录接口,获取用户数据 + 动态密钥(生产环境必须)
  const res = await loginApi({ username: 'test', password: '123456' });
  const { token, userInfo, cryptoKey, cryptoIV } = res.data;

  // 2. 更新加密密钥(替换临时密钥,核心安全操作)
  updateCryptoKey(cryptoKey, cryptoIV);

  // 3. 更新Store状态(插件自动加密存储到本地)
  userStore.login({ token, userInfo });
};

// 登出逻辑
const handleLogout = () => {
  userStore.logout(); // 重置状态 + 清除加密数据
};
</script>

步骤7:验证效果(可选)

打开浏览器开发者工具(F12)→ Application → Local Storage,查看存储的pinia_user值:

  • 加密后:是一串乱码字符串(如U2FsdGVkX1+...),无法直接读取;
  • 解密后:插件会自动将其还原为{ token: "...", userInfo: {...} }并同步到Store。

总结(核心关键点)

  1. 工具层封装:加解密函数独立封装,通过updateCryptoKey动态更新密钥(生产环境必须);
  2. 插件自动化:Pinia 插件监听状态变化,自动完成「加密存储 + 解密加载」,业务代码无感知;
  3. 按需加密:通过include配置只加密敏感Store(如user),减少性能损耗;
  4. 安全收尾:登出时必须调用$clearEncryptedStorage清除本地加密数据,防止信息泄露。

通过以上7步,即可将加解密逻辑无缝集成到 Pinia 状态管理中,既保证敏感数据安全,又不影响开发体验。

相关文章
|
3月前
|
JSON Java 编译器
Protobuf 是什么?一篇文章搞懂这个高性能序列化神器
Protobuf是Google开源的高效二进制序列化协议,体积小、速度快,支持跨语言、向后兼容。相比JSON,更适合RPC等高性能场景,广泛应用于微服务通信。通过`.proto`文件定义结构,自动生成代码,实现数据的快速序列化与反序列化。
1793 158
|
1月前
|
关系型数据库 MySQL Java
分布式事务终极指南:2PC/XA/TCC/SAGA 从底层原理到生产选型全拆解
本文系统解析分布式事务四大主流方案:XA/2PC(强一致但性能差)、TCC(高并发柔性事务)、SAGA(长事务最终一致)及理论基石(ACID/CAP/BASE),涵盖原理、流程、实战代码、优劣对比与生产选型标准,助你深入掌握核心逻辑。
544 3
|
2月前
|
机器学习/深度学习 数据采集 人工智能
OpAgent:登顶WebArena的多模态Web GUI Agent
蚂蚁集团自研多模态Web智能体OpAgent,以71.6%的成功率登顶WebArena榜单。该方案通过层次化多任务微调构建基座,利用在线强化学习与混合奖励机制应对环境动态性,并结合模块化架构实现复杂任务的稳健执行与自我修正,刷新了Web智能体领域的SOTA纪录。
281 11
|
3月前
|
网络协议 Dubbo Java
从 TCP 到 RPC:彻底搞懂「HTTP 与 RPC用法区别」
本文深入剖析HTTP与RPC的本质区别,从TCP底层原理讲起,解析粘包拆包、协议封装等核心问题,梳理二者演进脉络。通过对比服务发现、传输性能、适用场景等维度,结合Dubbo、gRPC等框架,帮你按场景精准选型,彻底搞懂微服务通信的技术逻辑。
666 160
|
3月前
|
安全 应用服务中间件 Linux
HTTPS 优化完整方案解析
本文详解HTTPS性能优化全方案,从原理到实操,涵盖硬件加速(AES-NI)、软件升级(内核与OpenSSL)及协议层优化(TLS 1.3、ECDSA、会话复用等),配合Nginx配置模板与验证方法,助你实现安全与速度双提升,显著降低访问延迟。
1258 156
Idea 项目结构不显示解决方案
Idea 项目结构不显示解决方案
1362 0
Idea 项目结构不显示解决方案
|
4月前
|
人工智能 安全 搜索推荐
钉钉发布全球首个工作智能操作系统Agent OS,专为AI打造
2025年12月23日,钉钉在杭州发布AI钉钉1.1“木兰”版本,推出全球首个为AI打造的工作智能操作系统——Agent OS,开启“人与AI协同”新范式。通过钉钉ONE、DingTalk Real、AI搜问、悟空Agent及DEAP平台等构建完整AI协作体系,实现AI直连物理世界。发布会推出超20款AI产品,涵盖制造、差旅、客服等场景,全面升级AI表格、AI听记、DingTalk A1,助力企业零门槛迈向AI原生办公。
6547 10
|
1月前
|
人工智能 机器人 BI
3 步搞定!在飞书批量创建小龙虾对话框,每个对话框各司其职、自动执行不同任务。保姆级教程,一看就会!
本文详解如何用飞书+OpenClaw高效管理“小龙虾”AI助手:通过创建专属飞书群、添加角色化Agent(如“内容高手”)、绑定群ID三步,实现任务隔离与精准响应。无需编程基础,1小时即可完成配置,提升执行准确率与响应速度。
|
1月前
|
人工智能 网络安全 开发工具
让OpenClaw价值翻倍:阿里云/本地部署与10个官方skill 解锁 AI Agent 效率上限
大多数人使用OpenClaw时,仅停留在“指令-输出”的基础层面,却忽略了其背后可深度挖掘的效率杠杆。OpenClaw的核心瓶颈与Claude Code一致——上下文窗口是有限的“白板”,如何让这块白板发挥最大价值,决定了AI开发的效率上限。
363 11
|
1月前
|
自然语言处理 调度 语音技术
一行 Python,三种世界:聊聊文本 + 图像 + 音频的多模态协同生成
一行 Python,三种世界:聊聊文本 + 图像 + 音频的多模态协同生成
173 4

热门文章

最新文章

下一篇
开通oss服务