前后端通信加密解密完整方案实现

概述

本文将详细介绍一个基于Vue3 + Pinia + Axios的前后端通信加密解密方案。该方案采用RSA+AES混合加密机制,确保数据传输的安全性。

技术栈

  • • 前端框架: Vue3 + Pinia
  • • 加密库: crypto-js + jsencrypt
  • • HTTP客户端: Axios

加密方案设计

1. 加密策略

采用混合加密机制:

  • • AES加密: 用于加密大量业务数据(对称加密,效率高)
  • • RSA加密: 用于加密AES密钥(非对称加密,安全性高)

2. 加密流程





核心实现

1. 加密存储 (crypto.js)

import { defineStore } from "pinia";
import CryptoJS from "crypto-js";
import JSEncrypt from "jsencrypt/bin/jsencrypt.min";

export default defineStore("cryptoStore", {
  state() => ({
    backendPublicKeyimport.meta.env.VITE_APP_PUBLIC_KEY, // 后端rsa公钥
    frontendKeyAndIvArray: [], // 前端AES密钥与IV组合
  }),
  
  actions: {
    /**
     * 生成前端AES密钥和IV
     */
    generateFrontendKey(url) {
      // 生成32字节(256位)随机密钥
      const _AesKey = CryptoJS.lib.WordArray.random(32);
      const frontendKey = CryptoJS.enc.Base64.stringify(_AesKey);

      // 生成16字节(128位)随机IV
      const _iv = CryptoJS.lib.WordArray.random(16);
      const frontendIv = CryptoJS.enc.Base64.stringify(_iv);

      // 存储密钥对
      this.frontendKeyAndIvArray.push({
        url,
        key: frontendKey,
        iv: frontendIv,
      });

      return { key: frontendKey, iv: frontendIv };
    },

    /**
     * 准备加密载荷
     */
    async prepareEncryptedPayload(url, datajson) {
      // 生成密钥和IV
      const frontendKeyIv = this.generateFrontendKey(url);
      
      // 序列化数据
      const text = typeof datajson === 'string' 
        ? datajson 
        : JSON.stringify(datajson);

      // AES-CBC加密
      const dataCipher = CryptoJS.AES.encrypt(
        text,
        CryptoJS.enc.Base64.parse(frontendKeyIv.key),
        {
          iv: CryptoJS.enc.Base64.parse(frontendKeyIv.iv),
          mode: CryptoJS.mode.CBC,
          padding: CryptoJS.pad.Pkcs7,
        }
      ).toString();

      // RSA加密AES密钥
      const rsa = new JSEncrypt();
      rsa.setPublicKey(this.backendPublicKey);
      const encryptKey = rsa.encrypt(frontendKeyIv.key);
      
      if (!encryptKey) throw new Error("RSA公钥加密失败");

      return {
        encryptKey,
        iv: frontendKeyIv.iv,
        data: dataCipher,
      };
    },

    /**
     * 解密并销毁密钥
     */
    decryptAndDestroy(requestConfig, ciphertext) {
      if (!ciphertext) return null;

      // 查找对应的密钥和IV
      const frontendKeyIv = this.frontendKeyAndIvArray.find(
        (item) => item.iv === requestConfig.headers["X-Encrypt-Iv"]
      );

      if (!frontendKeyIv) {
        throw new Error("前端密钥/IV不存在");
      }

      // AES解密
      const bytes = CryptoJS.AES.decrypt(
        ciphertext,
        CryptoJS.enc.Base64.parse(frontendKeyIv.key),
        {
          iv: CryptoJS.enc.Base64.parse(frontendKeyIv.iv),
          mode: CryptoJS.mode.CBC,
          padding: CryptoJS.pad.Pkcs7,
        }
      );

      const plain = bytes.toString(CryptoJS.enc.Utf8);
      
      // 销毁密钥
      this.destroyCurrentKeyAndIv(frontendKeyIv.iv);

      // 尝试解析JSON
      try {
        return JSON.parse(plain);
      } catch (e) {
        return plain;
      }
    },

    /**
     * 销毁指定密钥
     */
    destroyCurrentKeyAndIv(iv) {
      this.frontendKeyAndIvArray = this.frontendKeyAndIvArray.filter(
        (item) => item.iv !== iv
      );
    },
  },
});Code language: JavaScript (javascript)

2. Axios拦截器配置 (request.js)

import axios from "axios";
import useCryptoStore from "@/store/modules/crypto";

// 创建axios实例
const service = axios.create({
  baseURLimport.meta.env.VITE_APP_BASE_API,
  timeout30 * 1000,
});

// 请求拦截器
service.interceptors.request.use(
  async (config) => {
    const cryptoStore = useCryptoStore();
    
    // 是否需要加密(通过请求头控制)
    const notCrypto = (config.headers || {}).notCrypto === false;
    
    if (!notCrypto) {
      // 加密请求数据
      const crypto = await cryptoStore.prepareEncryptedPayload(
        config.url, 
        config.data
      );
      
      // 设置加密相关请求头
      config.headers["X-Encrypt-Key"] = crypto.encryptKey;
      config.headers["X-Encrypt-Iv"] = crypto.iv;
      config.data = { data: crypto.data };
    }
    
    return config;
  },
  (error) => {
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (res) => {
    const code = res.data.code || 200;
    
    // 二进制数据直接返回
    if (res.request.responseType === "blob" || 
        res.request.responseType === "arraybuffer") {
      return res.data;
    }
    
    // 错误处理
    if (code !== 200) {
      // ... 错误处理逻辑
      return Promise.reject(new Error(msg));
    }
    
    // 解密响应数据
    const cryptoStore = useCryptoStore();
    let decryptedData = null;
    
    if (res.data.data || res.data.rows) {
      decryptedData = cryptoStore.decryptAndDestroy(
        res.config,
        res.data.data ?? res.data.rows
      );
      
      // 更新响应数据 根据实际情况进行调整
      if (res.data.data !== undefined) res.data.data = decryptedData;
      if (res.data.rows !== undefined) res.data.rows = decryptedData;
    }
    
    return Promise.resolve(res.data);
  },
  (error) => {
    // ... 错误处理
    return Promise.reject(error);
  }
);

export default service;Code language: JavaScript (javascript)

使用方法

1. 环境配置

# .env.development
VITE_APP_PUBLIC_KEY=后端RSA公钥
VITE_APP_BASE_API=http://localhost:8080/api
VITE_APP_ENV=developmentCode language: PHP (php)

2. 在组件中使用

import axios from '@/utils/request';

// 发送加密请求
const sendEncryptedRequest = async () => {
  try {
    const response = await axios.post('/user/info', {
      username'test',
      password'123456'
    });
    console.log('解密后的数据:', response);
  } catch (error) {
    console.error('请求失败:', error);
  }
};

// 跳过加密(通过请求头控制)
const sendNormalRequest = async () => {
  const response = await axios.post('/public/info', {
    data'public data'
  }, {
    headers: {
      notCryptotrue  // 跳过加密
    }
  });
};Code language: JavaScript (javascript)

安全性考虑

1. 密钥管理

  • • ✅ 每次请求生成独立的AES密钥和IV
  • • ✅ 请求完成后立即销毁前端密钥
  • • ✅ 使用RSA公钥加密传输AES密钥

2. 加密算法

  • • ✅ AES-256-CBC:高强度对称加密
  • • ✅ RSA:非对称加密保护密钥传输
  • • ✅ PKCS7填充:标准填充方式

3. 传输安全

  • • ✅ HTTPS传输(生产环境)
  • • ✅ 自定义加密头标识
  • • ✅ 防重放攻击(时间戳验证)

还能进行的性能优化:

1. 加密性能

- 使用Web Workers进行大量数据加密(可选)
- 异步加密避免阻塞主线程

 2. 内存管理

- 及时清理敏感数据
- 使用Array.filter销毁密钥引用

3. 网络优化

- 支持请求缓存配置
- 二进制数据跳过加密处理Code language: CSS (css)

部署建议

1. 生产环境配置

# .env.production
VITE_APP_PUBLIC_KEY=生产环境RSA公钥
VITE_APP_BASE_API=https://api.production.com
VITE_APP_ENV=productionCode language: PHP (php)

2. 性能监控

// 添加性能监控
const startTime = performance.now();
// ... 加密操作
const encryptTime = performance.now() - startTime;
console.log(`加密耗时: ${encryptTime}ms`);Code language: JavaScript (javascript)

3. 安全审计

  • • 定期检查加密算法安全性
  • • 更新密钥对(建议每3-6个月)
  • • 监控异常请求模式

总结

本方案提供了一个完整的前后端通信加密解决方案,具有以下特点:

✅ 安全性高:RSA+AES混合加密,确保数据传输安全
✅ 性能优秀:AES加密大量数据,RSA只加密密钥
✅ 易于集成:基于Axios拦截器,对业务代码无侵入
✅ 灵活配置:支持跳过加密、自定义加密策略
✅ 内存安全:及时销毁敏感数据,防止内存泄漏

通过这套方案,可以有效保护前后端通信数据,防止中间人攻击、数据泄露等安全风险。