尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
纯JS实现的加解密方法
crypto-js4.2.0 uni-app 请求封装 AES 加解密 URL 编码一、安装指定版本依赖npm install crypto-js4.2.0 --save安装后查看package-lock.json确认片段crypto-js: { version: 4.2.0, resolved: https://registry.npmmirror.com/crypto-js/-/crypto-js-4.2.0.tgz, integrity: sha512-KALDyEYgpYRlob/iriUtjV6d5EqY191A5g4UqLAi8CyGP9N1FdVbkc1SxKc2r4YAYqG8JzO2KGLAizD70Q }二、新建工具文件/utils/aesDecrypt.js包含解密函数、配套加密函数passwordEncryption请求里用到的加密方法、统一封装解密后端数据import CryptoJS from crypto-js; /** * AES解密方法 (CBC模式) * param {String} encryptedData 加密后的Base64密文 * param {String} key 密钥16位AES-128 * param {String} iv 初始化向量 固定16位 * returns {String} 解密后原始字符串 */ export function aesDecrypt(encryptedData, key, iv) { try { // Base64密文转WordArray const encryptedHexStr CryptoJS.enc.Base64.parse(encryptedData); // 密钥、iv转WordArray const keyHex CryptoJS.enc.Utf8.parse(key); const ivHex CryptoJS.enc.Utf8.parse(iv); const decrypted CryptoJS.AES.decrypt( { ciphertext: encryptedHexStr }, keyHex, { iv: ivHex, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 } ); return decrypted.toString(CryptoJS.enc.Utf8); } catch (error) { console.error(AES解密失败:, error); throw new Error(解密失败请检查密钥、向量和密文是否正确); } } /** * AES加密方法对应前端请求参数加密 passwordEncryption * param {String} plainText 原始明文JSON字符串 * param {String} key 密钥 * param {String} iv 向量 * returns {String} Base64密文 */ export function passwordEncryption(plainText, key, iv) { const keyHex CryptoJS.enc.Utf8.parse(key); const ivHex CryptoJS.enc.Utf8.parse(iv); const encrypted CryptoJS.AES.encrypt(plainText, keyHex, { iv: ivHex, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.Pkcs7 }); return encrypted.toString(); } /** * 统一解密后端返回加密数据 * 内置约定好的固定key、iv与后端保持一致 * param {String} encryptedData 后端返回Base64密文 * returns {String} 原始JSON字符串 */ export function decryptBackendData(encryptedData) { // 业务固定密钥IV正式环境建议接口下发不硬编码 const key 1111111111111111; // 修正必须严格16位 const iv 1111111111111111; // 修正必须严格16位 return aesDecrypt(encryptedData, key, iv); } /** * 统一加密请求参数内置固定key iv * param {String} plainText JSON字符串 * returns {String} Base64密文 */ export function encryptReqData(plainText) { const key 1111111111111111; const iv 1111111111111111; return passwordEncryption(plainText, key, iv); }三、request 请求封装增加import config from ../static/config.js; // 引入加解密工具 import { decryptBackendData, encryptReqData } from /utils/aesDecrypt.js; // 你的全局配置、接口域名、config等自行保留 import config from /config/index.js; const fetch { interfaceUrl: function() { //接口地址 let server config.server(); return server; }, }; export default { /** * 通用请求封装 * param {String} url 接口地址 * param {Object} postData 请求参数 * param {String} method 请求方式 GET/POST * param {Boolean} type true:x-www-form / false:json * param {Boolean} showLoading 是否展示loading * returns {Promise} */ request: function(url, postData, method, type, showLoading) { // 展示加载弹窗 if (showLoading) { uni.showLoading({ mask: true, title: 请稍候... }) } // 自动注入openid if (postData) { const userStorage uni.getStorageSync(user); if (userStorage userStorage.length) { postData.openid userStorage; } } console.log(当前请求地址, url); console.log(原始请求参数, postData); //从这开始 // 接口白名单白名单接口不加密请求参数 const encryptWhiteList [ /rsp/api/rsp/inspector/snapshot/save, /rsp/api/rsp/inspector/create/lunei/order/time ]; // 不在白名单则加密参数 if (!encryptWhiteList.includes(url)) { // 1. 对象转JSON字符串 2.AES加密 3.URL编码防止 / 被转义 const jsonStr JSON.stringify(postData); const aesCipher encryptReqData(jsonStr); postData { encryptData: encodeURIComponent(aesCipher) }; console.log(加密后请求参数 postData, postData); } return new Promise((resolve, reject) { uni.request({ url: fetch.interfaceUrl() url, data: postData, header: { content-type: type ? application/x-www-form-urlencoded : application/json, authorization: uni.getStorageSync(token) || , security: 1, merchantid: config.merchantid(), code: uni.getStorageSync(code) || }, method: method, dataType: json, timeout: 60000, success: (res) { // 返回数据解密白名单该接口不解密后端数据 const decryptWhiteList [ /rsp/api/rsp/user/order/jieshunadd ]; if (!decryptWhiteList.includes(url)) { try { const jsonData res.data; // 解密Base64密文 const decodeData decryptBackendData(jsonData); // 覆盖res为解密后的真实JSON对象 res JSON.parse(decodeData); } catch (err) { console.error(返回数据解密解析失败, err); } } console.log(当前返回地址, url); console.log(处理后返回数据, res); showLoading uni.hideLoading(); resolve(res); }, fail: (res) { uni.showToast({ title: res.errMsg || 出错啦~, icon: none, duration: 2000 }); // 失败回调尝试解密返回数据 if (url ! / url ! ) { const jsonData res.data; if (jsonData) { try { const decodeData decryptBackendData(jsonData); res JSON.parse(decodeData); } catch (err) { console.error(失败回调解密异常, err); } } } showLoading uni.hideLoading(); reject(res); } }) }) } }四、加密开关优化方案总结1. 配置文件static/config.js新增加密控制开关作用一键全局开启 / 关闭接口 AES 加密无需修改请求逻辑// 接口加密开关0关闭加密1开启AES加密 const encrypt function() { return 1; } module.exports { encrypt: encrypt }2. 请求文件request.js接入开关控制引入配置import config from ../static/config.js在原有非白名单加密判断处增加开关校验// 原判断不在白名单就加密 // 修改后不在白名单 且 加密开关1 才执行加密 if (!encryptWhiteList.includes(url) config.encrypt() 1) { // AES加密 encodeURIComponent编码逻辑不变 }调试 / 本地环境将 config 中 return 改为 0全局接口明文传输线上改为 1 开启加密。五、注意小问题1.encodeURIComponent 在 AES 加密场景1. 两个 URL 编码函数区分方法转义范围使用场景encodeURI仅转义 URL 非法字符保留/?:拼接完整页面 URL不用于接口参数encodeURIComponent转义 / ? 空格等所有特殊符号接口传输 AES 密文必须使用(2). AES 密文必须编码的核心原因CryptoJS 加密输出标准 Base64 字符串包含三类危险字符 / URL 传输时会被后端自动解析为空格/、会切割参数键值对密文结构损坏没有这个最终结果导致后端解密失败、返回空字符串(这个问题要注意)2. 前后端配套流程前端请求加密流程对象 JSON 字符串 → AES 加密得到 Base64 密文 →encodeURIComponent(密文)→ 传给后端后端接收解密流程接收参数 →decodeURIComponent(加密字符串)还原原始 Base64 → AES 解密解密时必须先执行decodeURIComponent再传入 AES 解密函数顺序不可颠倒3.GET 请求GET 请求 URL 拼接参数强制使用 encodeURIComponent例子encodeURIComponent this.$request(/rsp/api/stc/park/?keyappberthcodeupdateplateno, GET).then((res) { if (res.data.keyappvalue 1) { this.plateNoBtn true } this.getDetail (); })你封装的$request内部会自动处理参数拼接 编码这种自动传keyapp过去的后端收不到的要修改成以下的就可以实现postdata加密传输过去this.$request( this.$request(/rsp/api/stc/park/, {keyapp: berthcodeupdateplateno}).then((res) {.then((res) { if (res.data.keyappvalue 1) { this.plateNoBtn true } this.getDetail() })请求封装内部会自动对每个参数执行encodeURIComponent编码适配 AES 密文、特殊字符场景参数和 url 分离后续新增参数直接往对象里加不用手动拼接可读性、维护性更强统一走你之前配置的加密开关逻辑若接口不在白名单会自动加密。3. POST-JSON 传参axios 会自动处理转义但统一编码能兼容所有后端框架建议保留
RELATED

相关推荐

Vue3 组合式函数的性能审视:避免不必要的响应式依赖与重复计算

Vue3 组合式函数的性能审视:避免不必要的响应式依赖与重复计算

Vue3 组合式函数的性能审视:避免不必要的响应式依赖与重复计算 一、Composable 的隐蔽性能陷阱 Vue3 的组合式 API 极大提升了逻辑复用能力,但也带来了新的性能陷阱。最常见的问题:composable 内部创建的响应式引用在组件中被重复收集依赖&am…

📅 2026/9/10 17:33:41
从 JS 的 `.call()` 到 Java 的“反射”:我是如何降维理解 Java 反射的

从 JS 的 `.call()` 到 Java 的“反射”:我是如何降维理解 Java 反射的

💡 前言:被“反射”概念整懵的瞬间 作为一个有前端背景、正在啃 Java 后端的开发者,我在学习 Spring Boot 企业级开发(比如用 AOP 实现公共字段自动填充)时,遇到了下面这段让人血压飙升的“天书”&#xff…

📅 2026/9/10 17:32:51
马尔可夫【MDP】

马尔可夫【MDP】

Alice 和 Bob 正在玩一个 k 轮的石头剪刀布游戏。游戏开始时,两位玩家各有恰好 3 张牌,每张牌是石 头(R)、剪刀(S)或布(P)。每一轮游戏按照如下方式进行: 1. 双方均可看见…

📅 2026/9/10 18:09:46
MORE NEWS

更多资讯

📰

Bilibook:Windows平台轻量级知识管理工具部署指南

1. Bilibook项目概述Bilibook是一个基于Windows平台的轻量级知识管理工具,专为中文用户设计。它采用本地化部署方案,无需复杂配置即可快速搭建个人知识库系统。作为一位长期使用各类笔记软件的资深用户,我发现Bilibook在以下场景特别实用&…

📰

【Rust入门知识点学与练】第12课:结构体 Struct

知识点1:定义和使用结构体 结构体让你把相关的数据组合在一起: // 定义结构体 struct Student {name: String,age: u32,score: f64, }fn main() {// 创建结构体实例let s1 Student {name: String::from("小明"),age: 18,score: 95.5,};// 访问…

📰

HDFS副本机制:原理、配置与生产实践

1. HDFS副本机制的核心价值与设计哲学在分布式存储系统中,数据可靠性始终是首要考量。HDFS作为Hadoop生态的核心存储组件,其副本机制的设计直接决定了数据安全性和集群吞吐能力。我曾在PB级集群运维中亲历过因副本配置不当导致的数据丢失事故&#xff0c…

📰

基于YOLOv8-pose的游泳动作识别实战:数据标注、训练与Gradio部署

简介:面向计算机视觉方向学生与毕业设计开发者,这份资源提供一套基于YOLOv8的游泳动作识别系统,包含完整可运行的源码、配套数据集、可视化界面与部署说明,适合快速复现并用于毕设、课程设计或初期立项演示。资源共97个文件&#…

📰

LangGraph智能体与长期记忆

LangGraph 智能体与长期记忆:从无状态对话到有记忆的协作者摘要:本文基于 DeepLearning.AI《LangGraph 中的 AI 代理》与《基于 LangGraph 的长期代理记忆》两门课程实践,拆解 LangGraph 智能体的三大核心机制:StateGraph 状态流、…

📰

Java聊天系统设计与实现:Socket多线程并发编程实战

简介:面向需要学习 Java 网络编程、完成课程设计或毕业设计的开发者,这一基于 Java 的聊天系统设计与实现资源提供了从客户端到服务器端的完整方案。资源包大小约 518KB,内含源代码、系统运行截图、项目报告和使用说明文档,覆盖用…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬