前后端通信加密解密完整方案实现
- Vue
- 26天前
- 85热度
概述
本文将详细介绍一个基于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: () => ({
backendPublicKey: import.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({
baseURL: import.meta.env.VITE_APP_BASE_API,
timeout: 30 * 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: {
notCrypto: true // 跳过加密
}
});
};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拦截器,对业务代码无侵入
✅ 灵活配置:支持跳过加密、自定义加密策略
✅ 内存安全:及时销毁敏感数据,防止内存泄漏
通过这套方案,可以有效保护前后端通信数据,防止中间人攻击、数据泄露等安全风险。
