纯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 会自动处理转义但统一编码能兼容所有后端框架建议保留

相关新闻

WebAssembly AI 推理精度损失:量化之后模型的答案还靠谱吗

WebAssembly AI 推理精度损失:量化之后模型的答案还靠谱吗

WebAssembly AI 推理精度损失:量化之后模型的答案还靠谱吗专栏: AI / WASM AI / 量化推理一、WASM 跑 AI 的诱惑和现实的鸿沟 去年我在浏览器里跑了一个微型 LLM,用的 llama.cpp 编译到 WASM。模型加载成功的那一刻确实激动——不需要服务器、不需要 GPU…

2026/10/18 6:44:37 阅读更多 →
日常护牙常见误区盘点|普通人该如何科学做好口腔长期养护

日常护牙常见误区盘点|普通人该如何科学做好口腔长期养护

【本文为口腔健康科普,含少量机构科普向推荐,非医疗广告】前言口腔健康是全身健康的重要组成部分,但很多人在刷牙、洗牙、牙齿护理上存在不少认知偏差,长期错误习惯会慢慢引发蛀牙、牙龈红肿、牙周不适等问题。本文从日常居家护理…

2026/10/20 3:39:01 阅读更多 →
Tokio 替代方案对比:smol、async-std 和 glommio 各自适合什么场景

Tokio 替代方案对比:smol、async-std 和 glommio 各自适合什么场景

Tokio 替代方案对比:smol、async-std 和 glommio 各自适合什么场景专栏: 技术 / Tokio / Rust异步运行时一、Tokio 一家独大,但选择从来不是唯一的 Rust 异步生态有个有趣的现象:Tokio 占据了绝对主导地位,导致很多人以为"Ru…

2026/10/18 6:45:35 阅读更多 →

最新新闻

腾讯云ASR实时语音识别前端接入:WebSocket签名与音频处理实战

腾讯云ASR实时语音识别前端接入:WebSocket签名与音频处理实战

前阵子我在给一个内部工具加“实时转写”功能,要把对话语音实时转成文字用于内容分析。调研了一圈,最后选了腾讯云 ASR 实时语音识别。原本以为就是“拿麦克风录音,发到 WebSocket,收文本”三件事,实际做下来发现每个环…

2026/10/21 3:54:34 阅读更多 →
Linux V4L2视频采集四步流程:打开→查询→设置→启动

Linux V4L2视频采集四步流程:打开→查询→设置→启动

1. 项目概述:为什么V4L2是Linux视频设备的“底层语言”在Linux系统里,但凡你接触过USB摄像头、树莓派CSI模组、工业面阵相机,甚至某些PCIe采集卡,几乎绕不开一个词:V4L2。它不是某个具体软件,也不是命令行工…

2026/10/21 3:54:34 阅读更多 →
Flutter GestureDetector 手势系统深度解析:从原理到高性能实践

Flutter GestureDetector 手势系统深度解析:从原理到高性能实践

1. 为什么说 GestureDetector 是 Flutter 手势世界的“总开关”在 Flutter 开发中,你写过多少次onTap?又是否曾疑惑:明明只是点了一下屏幕,背后却触发了onTapDown、onTapUp、onTapCancel一整套回调?或者,你…

2026/10/21 3:54:34 阅读更多 →
Qwen2.5-VL跨硬件微调:LoRA与OFT在昇腾910B与4090上的实战

Qwen2.5-VL跨硬件微调:LoRA与OFT在昇腾910B与4090上的实战

这个项目的起因很现实:手上的多模态微调代码在单张4090上调得好好的,业务方突然要求国产算力平台也能跑,而基于Qwen2.5-VL的私域图像理解任务又必须保留原有效果。于是就有了标题里那条主线——从LoRA到OFT,从昇腾910B到4090&…

2026/10/21 3:54:34 阅读更多 →
深入Linux内存管理:伙伴系统与slab分配器核心原理

深入Linux内存管理:伙伴系统与slab分配器核心原理

前段时间在压测一个存储服务时,我发现一个奇怪的现象:明明内存总量还很充足,但每次接口申请一个8KB的连续块时,耗时总会偶发冲到几百微秒甚至毫秒级。查到最后,问题不在业务代码,而在内存管理这一层——更具…

2026/10/21 3:54:34 阅读更多 →
FFmpeg输入源处理:本地文件与网络流读取的底层逻辑与实战

FFmpeg输入源处理:本地文件与网络流读取的底层逻辑与实战

FFmpeg 这个工具,刚接触音视频开发的人往往会被它庞大的参数体系劝退,但真正用起来之后又会发现,很多看似复杂的需求,其实一条命令就能搞定。这次要聊的是 FFmpeg 读取本地文件和网络流这两种输入源的处理方式,属于系列…

2026/10/21 3:53:34 阅读更多 →

日新闻

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

统一内存+量化:锐龙AI Max PRO 400如何本地跑320B大模型

这段时间硬件圈和AI圈都在传一个事:AMD锐龙AI Max PRO 400系列把最高192GB统一内存搬进了PC形态的产品里,按宣传口径,本地跑320B参数的大家伙不再是纸面概念。我第一反应倒不是“内存真大”,而是这话背后的含金量——它把过去只能…

2026/10/21 0:00:11 阅读更多 →
AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

AI助手深度使用体验:对话质量、长文本处理与指令遵循如何留住用户

1. 从“封号重开”这个行为说起:用户到底在追求什么“封号重开”这四个字,放在任何产品语境里都带着一股决绝的味道。一个账号从零开始积累使用记录、调教偏好、沉淀工作流,背后是大量的时间和精力成本。正常情况下,没有人愿意主动…

2026/10/21 0:00:11 阅读更多 →
ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

ROS中YOLOv3工程落地:通信同步、坐标变换与性能调优

1. 为什么在ROS里硬刚YOLOv3不是“炫技”,而是工程落地的必经之路我第一次在某高校机器人实验室看到那台搭载Jetson TX2的移动底盘原地打转、反复识别错垃圾桶时,就意识到:单纯跑通darknet_ros demo和真正让YOLOv3在ROS里“干活”&#xff0c…

2026/10/21 0:00:11 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/20 20:43:59 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →