uni-app和springboot完成前端后端对称加密解密流程
概述
- 使用对称加密的方式实现。
- 前端基于crypto-js。
- uni-app框架中是在uni.request的基础上,在拦截器中处理的。
- springboot在Filter中完成解密工作。
uni-app
- 项目中引入crypto-js。
npm install crypto-js
- 加密方法
const SECRET_KEY = CryptoJS.enc.Utf8.parse("1234123412341234");function encrypt (msg) {const dataHex = CryptoJS.enc.Utf8.parse(msg);const encrypted = CryptoJS.AES.encrypt(dataHex, SECRET_KEY, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return encrypted.ciphertext.toString(CryptoJS.enc.Base64);
}
- 解密方法
function decrypt(msg) {const encryptedHexStr = CryptoJS.enc.Hex.parse(msg);const str = CryptoJS.enc.Base64.stringify(encryptedHexStr);const decrypt = CryptoJS.AES.decrypt(str, SECRET_KEY, {mode: CryptoJS.mode.ECB,padding: CryptoJS.pad.Pkcs7});return decrypt.toString(CryptoJS.enc.Utf8);
}
- request拦截器
uni.addInterceptor('request', {invoke(args) {let plaintext = JSON.stringify(args.data);plaintext = encodeURIComponent(plaintext);const textArray = [];while(plaintext.length > 15) {textArray.push(plaintext.substring(0, 16));plaintext = plaintext.substring(16);}textArray.push(plaintext);const encryptParamArray = [];textArray.forEach(item => {encryptParamArray.push(btoa(encrypt(item)));})args.data = {"encryptParams": encryptParamArray};},success(args) {}, fail(err) {}, complete(res) {}
});
备注
- 使用encodeURIComponent方法是为了处理 字符“+”,这个对应java解密的时候存在问题。
- 该模式默认解密长度出限制在16个字符中,所以需要将待加密的信息分解成单个字符长度小于16的字符组成数组。
Springboot
- DecryptFilter,解密拦截器
import cn.hutool.json.JSONUtil;
import org.apache.commons.codec.binary.Base64;
import org.springframework.http.HttpMethod;import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;@WebFilter(urlPatterns = "/*") // 过滤所有请求
public class DecryptFilter implements Filter {private String word;public DecryptFilter(String word) {this.word = word;}@Overridepublic void init(FilterConfig filterConfig) throws ServletException {}@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;if (HttpMethod.OPTIONS.matches(httpRequest.getMethod())) {filterChain.doFilter(httpRequest, servletResponse);return;}String encryptedData = "";if (httpRequest.getHeader("Content-Type").contains("x-www-form-urlencoded")) {// 获取请求参数或请求体中的加密数据encryptedData = httpRequest.getParameter("encryptParams");} else if (httpRequest.getHeader("Content-Type").contains("json")) {StringBuilder stringBuilder = new StringBuilder();try (InputStream inputStream = httpRequest.getInputStream();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) {String line;while ((line = bufferedReader.readLine()) != null) {stringBuilder.append(line);}}encryptedData = JSONUtil.parseObj(stringBuilder.toString()).get("encryptParams").toString();encryptedData = encryptedData.replaceAll("[\\[\\]\"]", "");}String[] ciphertextArray = encryptedData.split(",");// 解密操作,例如使用AES解密String decryptedData = "";try {decryptedData = decrypt(ciphertextArray);} catch (Exception e) {throw new RuntimeException("解密失败!", e);}// 重构ServletRequest,将解密后的数据设置到新的ServletRequest中ServletRequest modifiedRequest = new BodyRewritingRequestWrapper(httpRequest, decryptedData);// 继续执行过滤器链filterChain.doFilter(modifiedRequest, servletResponse);}@Overridepublic void destroy() {}private String decrypt(String[] encryptedTextArray) throws Exception {StringBuilder paramsJson = new StringBuilder("");// 创建解密器Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");byte[] keyBytes = word.getBytes(StandardCharsets.UTF_8);SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");cipher.init(Cipher.DECRYPT_MODE, keySpec);for (String ciphertext : encryptedTextArray) {byte[] decode = java.util.Base64.getDecoder().decode(ciphertext);byte[] encryptedBytes = Base64.decodeBase64(decode);byte[] decryptedBytes = cipher.doFinal(encryptedBytes);paramsJson.append(new String(decryptedBytes, StandardCharsets.UTF_8));}return URLDecoder.decode(paramsJson.toString(), "UTF-8");}
}
- BodyRewritingRequestWrapper,重写的ServletRequest对相关
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;public class BodyRewritingRequestWrapper extends HttpServletRequestWrapper {private String body;private JSONObject map;public BodyRewritingRequestWrapper(HttpServletRequest request, String body) {super(request);this.body = body;this.map = JSONUtil.parseObj(body);}@Overridepublic String getParameter(String name) {if (map.containsKey(name)) {return map.get(name).toString();}return super.getParameter(name);}@Overridepublic Map<String, String[]> getParameterMap() {Map<String, String[]> originalParameters = super.getParameterMap();Map<String, String[]> rewriteMap = new HashMap<>(originalParameters);map.forEach((key, value) -> rewriteMap.put(key, new String[]{value.toString()}));return rewriteMap;}@Overridepublic ServletInputStream getInputStream() throws IOException {final ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(body.getBytes());return new ServletInputStream() {public int read() throws IOException {return byteArrayInputStream.read();}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return true;}@Overridepublic void setReadListener(ReadListener readListener) {}};}@Overridepublic BufferedReader getReader() throws IOException {return new BufferedReader(new InputStreamReader(this.getInputStream()));}
}
- 注册拦截器
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;@Configuration
public class WebConfig {@Value("${decrypt.word}")private String word;@Beanpublic FilterRegistrationBean<DecryptFilter> myFilterRegistration() {FilterRegistrationBean<DecryptFilter> registration = new FilterRegistrationBean<>();registration.setFilter(new DecryptFilter(word));registration.addUrlPatterns("/*");registration.setName("decryptFilter");registration.setOrder(1); // 设置过滤器的顺序,根据实际需求设置return registration;}
}
相关文章:
uni-app和springboot完成前端后端对称加密解密流程
概述 使用对称加密的方式实现。前端基于crypto-js。uni-app框架中是在uni.request的基础上,在拦截器中处理的。springboot在Filter中完成解密工作。 uni-app 项目中引入crypto-js。 npm install crypto-js加密方法 const SECRET_KEY CryptoJS.enc.Utf8.parse(…...

【Unity造轮子】制作一个简单的2d抓勾效果(类似蜘蛛侠的技能)
前言 欢迎阅读本文,本文将向您介绍如何使用Unity游戏引擎来实现一个简单而有趣的2D抓勾效果,类似于蜘蛛侠的独特能力。抓勾效果是许多动作游戏和平台游戏中的常见元素,给玩家带来了无限的想象和挑战。 不需要担心,即使您是一…...
Unity 人物连招(三段连击)
一: 连招思路 首先人物角色上有三个攻击实例对象 Damage,每一个damage定义了攻击的伤害值,攻击距离,触发器名称,伤害的发起者,攻击持续时间,攻击重置时间,伤害的碰撞框大小等字段: …...
关于WSL以及docker连接adb的坑
结论 WSL可以连接到adb,需要和主机保持一致的adb型号。主机是windows还是macOS的docker没法直接连接到adb设备,只有主机为Linux才可以。其他平台只能通过TCP网络协议。 具体过程 关于WSL连接adb设备 windows安装adb工具(安装可以去官网下…...

python安装第三方包时报错:...\lib\site-packages\pip\_vendor\urllib3\response.py...
安装redis第三方包: pip install redis报错现象: 解决方法:使用以下命令可成功安装 pip install redis -i http://pypi.douban.com/simple --trusted-host pypi.douban.com...
腾讯云从业者认证考试考点——云存储产品
文章目录 存储产品功能云存储产品概述存储产品存储网关存储服务 存储分类按存储方式分按存储频率分 云存储与传统存储的区别功能需求性能需求容量扩展数据共享 云硬盘CBS产品概述归档存储和文件存储归档存储CAS文件存储CFS 对象存储存储网关存储网关的分类 云数据迁移CDM日志服…...

猿辅导Motiff与IXDC达成战略合作,将在UI设计领域推动AI革新更多可能性
近日,“IXDC 2023国际体验设计大会”在北京国家会议中心拉开序幕,3000设计师、1000企业、200全球商业领袖,共襄为期5天的用户体验创新盛会。据了解,此次大会是以“设计领导力”为主题,分享全球设计、科技、商业的前沿趋…...

条件操作符(三目操作符)
比如之前我们想写一个条件判断表达式是这样写的: 用操作符就可以这样写: 应用,比如求两个数的最大值...
(五)Unity开发Vision Pro——FAQ
常见问题 (FAQ) 1.问:我看到在visionOS 模拟器中运行的结果与在硬件上运行的结果不同 请注意,在模拟器中运行时,某些特定于硬件的功能不可用 - 最明显的是 AR 数据。这可能意味着 VisionOS 模拟器中的模拟结果可能与 Vision Pro 耳机上的模…...

GitOps 与 DevOps:了解关键差异,为企业做出最佳选择
在软件开发领域,GitOps 和 DevOps 是加强协作和实现软件交付流程自动化的重要技术。虽然这两种模式都旨在提高软件开发生命周期的效率,但它们的核心原则和实施方式却各不相同。 本篇文章将帮助您了解 GitOps 和 DevOps 之间的差异、它们的工作流程&am…...
Java实现Word文档转PDF,PDF转Word,PDF转Excel,PDF转换工具
前言 java实现word文档转PDF,PDF转word 解决只能转换4页问题 解决每页头部存在水印问题 实现 引入依赖 <dependency><groupId>com.documents4j</groupId><artifactId>documents4j-local</artifactId><version>1.0.3</ve…...

Docker部署ES服务,全量同步的时候内存爆炸,ES自动关闭,CPU100%
问题 使用canal-adapter全量同步(参考Canal Adapter1.1.5版本API操作服务,手动同步数据(4))的时候 小批量数据可以正常运行(几千条)只要数据量一大(上万条),…...

Python——添加照片边框
原图: 添加边框后: 添加边框会读取照片的exif信息如时间、相机型号、品牌以及快门焦段等信息,将他们显示在下面的边框中。 获取当前py文件路径 import os #get path that py file located def Get_Currentpath():file_path os.path.abspa…...

《高性能MySQL》——查询性能优化(笔记)
文章目录 六、查询性能优化6.1 查询为什么会慢6.2 慢查询基础:优化数据访问6.2.1 是否向数据库请求了不需要的数据查询不需要的记录多表关联时返回全部列总是取出全部列重复查询相同的数据 6.2.2 MySQL 是否在扫描额外的记录响应时间扫描的行数与返回的行数扫描的行…...

【Linux操作系统】编译过程中遇到的问题-为什么加-c?执行文件提示无法执行二进制文件?main函数参数argc和*argv[]的作用和理解?
在使用GCC编译器进行程序开发时,我们经常会遇到一些编译过程中的问题, 比如为什么要加上"-c"选项,以及为什么生成的可执行文件无法执行等问题。 本篇博客将详细介绍这些问题,并给出相应的代码和解释,帮助读者…...

【数据结构与算法——TypeScript】图结构(Graph)
【数据结构与算法——TypeScript】 图结构(Graph) 认识图结构以及特性 什么是图? 在计算机程序设计中,图结构 也是一种非常常见的数据结构。 但是,图论其实是一个非常大的话题 认识一下关于图的一些内容 图的抽象数据类型一些算法实现。 什么是图?…...
C语言字符串拷贝函数详解及示例代码
目录 简介字符串拷贝函数 strcpy字符串拷贝函数 strcpy_s使用示例注意事项结束语 1. 简介 字符串拷贝是C语言中常用的操作之一。当需要将一个字符串复制到另一个字符串数组中时,可以使用字符串拷贝函数来实现。C语言提供了多种字符串拷贝函数,其中最常…...

IntelliJ IDEA热部署:JRebel插件的安装与使用
热部署 概述JRebel 概述 热部署,指修改代码后,无需停止应用程序,即可使修改后的代码生效,其有利于提高开发效率。 热部署方式: 手动热部署:修改代码后,重新编译项目,然后启动应用程…...

iTOP-3568开发板使用OpenCV处理图像-颜色转换
本小节代码在配套资料“iTOP-3568 开发板\03_【iTOP-RK3568 开发板】指南教程 \04_OpenCV 开发配套资料\05”目录下,如下图所示: cv2.cvtColor()函数功能: 将一幅图像从一个色彩空间转换到另一个色彩空间。 函数原型: cv2.cvt…...
Python技巧----解压序列/可迭代对象赋值给多个变量
1 、解压序列赋值给多个变量 我们这里说的不是正常情况的一一赋值比如下面 >>> data = [ ACME, 5, 9, (2012, 12, 1) ] >>> name, shares, price, date = data >>> name ACME...

网络六边形受到攻击
大家读完觉得有帮助记得关注和点赞!!! 抽象 现代智能交通系统 (ITS) 的一个关键要求是能够以安全、可靠和匿名的方式从互联车辆和移动设备收集地理参考数据。Nexagon 协议建立在 IETF 定位器/ID 分离协议 (…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合
强化学习(Reinforcement Learning, RL)是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程,然后使用强化学习的Actor-Critic机制(中文译作“知行互动”机制),逐步迭代求解…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql
智慧工地管理云平台系统,智慧工地全套源码,java版智慧工地源码,支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求,提供“平台网络终端”的整体解决方案,提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

通过Wrangler CLI在worker中创建数据库和表
官方使用文档:Getting started Cloudflare D1 docs 创建数据库 在命令行中执行完成之后,会在本地和远程创建数据库: npx wranglerlatest d1 create prod-d1-tutorial 在cf中就可以看到数据库: 现在,您的Cloudfla…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了: 这一篇我们开始讲: 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下: 一、场景操作步骤 操作步…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

LLMs 系列实操科普(1)
写在前面: 本期内容我们继续 Andrej Karpathy 的《How I use LLMs》讲座内容,原视频时长 ~130 分钟,以实操演示主流的一些 LLMs 的使用,由于涉及到实操,实际上并不适合以文字整理,但还是决定尽量整理一份笔…...

接口自动化测试:HttpRunner基础
相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具,支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议,涵盖接口测试、性能测试、数字体验监测等测试类型…...
tomcat入门
1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效,稳定,易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...