【RuoYi-Vue-Plus】学习笔记 50 - 集成 JSEncrypt 实现请求加密传输(源码)

news2024/9/26 3:29:59

文章目录

    • 前言
    • 框架版本
      • 前端
      • 服务端
    • 框架集成
      • 前端集成
      • 1、总览
      • 2、代码实现
      • 服务端集成
      • 1、总览
      • 2、代码实现
      • 2.1、配置信息 `application.yml`
      • 2.2、配置类 `ApiDecryptProperties`
      • 2.3、过滤器 `CryptoFilter`
      • 2.4、包装类 `DecryptRequestBodyWrapper`
      • 2.5、加解密工具类 `EncryptUtils`
      • 2.6、自动装配 `ApiDecryptAutoConfiguration`
      • 请求测试
      • 1、测试方法
      • 2、输出
      • 3、Debug

前言

在开始本文内容前,首先说一声:大家节日快乐!

本文来简单分析一下框架中请求加密的实现方式。该功能来源于框架 pr!377,后续进行了优化并手动合并到了框架 5.X 分支,并在版本 v5.1.0 正式发布。

在这里插入图片描述

PR 详情(传送门):

在这里插入图片描述

下面来看下具体的实现方式。

框架版本

前端

  • jsencrypt:3.3.1
  • crypto-js:^4.1.1

package.json

在这里插入图片描述

服务端

  1. 框架版本:v5.1.0
  2. Hutool 工具包(hutool-crypto):5.8.22

框架集成

在上面的 PR 详情里面已经描述了具体的实现方式,下面分别对前端后端进行说明,前端部分由于是小白,所以只把相关的代码贴出来。

前端集成

1、总览

实现思路:

  1. 随机生成密钥
  2. 对密钥进行 Base64 编码,并使用 RSA 公钥加密密钥,加入请求头
  3. 使用密钥对请求体进行 AES 加密

在这里插入图片描述

2、代码实现

请求拦截器:
request.ts

在这里插入图片描述

随机生成AES密钥:
generateAesKey

在这里插入图片描述

对AES密钥进行Base64编码:
encryptBase64

在这里插入图片描述

编码后使用 RSA 公钥加密:
.env.development

在这里插入图片描述

RSA 公私钥应由服务端定义,前端持有公钥对数据加密,且两端公钥需要保持一致。

jsencrypt.ts

在这里插入图片描述

使用AES密钥对请求体进行加密:
crypto.ts

在这里插入图片描述

服务端集成

1、总览

实现思路:

  1. 编写 yaml 配置信息,生成公私钥
  2. 编写配置类
  3. 编写过滤器实现解密逻辑
  4. 配置过滤器

加密模块 ruoyi-common-encrypt

在这里插入图片描述

2、代码实现

2.1、配置信息 application.yml

在这里插入图片描述

2.2、配置类 ApiDecryptProperties

在这里插入图片描述

2.3、过滤器 CryptoFilter

在这里插入图片描述

2.4、包装类 DecryptRequestBodyWrapper

在这里插入图片描述

对于请求数据的解密主要在这个方法中实现。

完整代码:

package org.dromara.common.encrypt.filter;

import cn.hutool.core.io.IoUtil;
import jakarta.servlet.ReadListener;
import jakarta.servlet.ServletInputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletRequestWrapper;
import org.dromara.common.core.constant.Constants;
import org.dromara.common.encrypt.utils.EncryptUtils;
import org.springframework.http.MediaType;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;

/**
 * 解密请求参数工具类
 *
 * @author wdhcr
 */
public class DecryptRequestBodyWrapper extends HttpServletRequestWrapper {

    private final byte[] body;

    public DecryptRequestBodyWrapper(HttpServletRequest request, String publicKey, String privateKey, String headerFlag) throws IOException {
        super(request);
        // 获取 AES 密码 采用 RSA 加密
        String headerRsa = request.getHeader(headerFlag);
        String decryptAes = EncryptUtils.decryptByRsa(headerRsa, privateKey);
        // 解密 AES 密码
        String aesPassword = EncryptUtils.decryptByBase64(decryptAes);
        request.setCharacterEncoding(Constants.UTF8);
        byte[] readBytes = IoUtil.readBytes(request.getInputStream(), false);
        String requestBody = new String(readBytes, StandardCharsets.UTF_8);
        // 解密 body 采用 AES 加密
        String decryptBody = EncryptUtils.decryptByAes(requestBody, aesPassword);
        body = decryptBody.getBytes(StandardCharsets.UTF_8);
    }

    @Override
    public BufferedReader getReader() {
        return new BufferedReader(new InputStreamReader(getInputStream()));
    }


    @Override
    public int getContentLength() {
        return body.length;
    }

    @Override
    public long getContentLengthLong() {
        return body.length;
    }

    @Override
    public String getContentType() {
        return MediaType.APPLICATION_JSON_VALUE;
    }


    @Override
    public ServletInputStream getInputStream() {
        final ByteArrayInputStream bais = new ByteArrayInputStream(body);
        return new ServletInputStream() {
            @Override
            public int read() {
                return bais.read();
            }

            @Override
            public int available() {
                return body.length;
            }

            @Override
            public boolean isFinished() {
                return false;
            }

            @Override
            public boolean isReady() {
                return false;
            }

            @Override
            public void setReadListener(ReadListener readListener) {

            }
        };
    }
}

2.5、加解密工具类 EncryptUtils

EncryptUtils#decryptByRsa

在这里插入图片描述

EncryptUtils#decryptByBase64

在这里插入图片描述

EncryptUtils#decryptByAes

在这里插入图片描述

2.6、自动装配 ApiDecryptAutoConfiguration

在这里插入图片描述

在这里插入图片描述

请求测试

1、测试方法

登录: [POST] /auth/login

2、输出

对解密信息输出一下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

3、Debug

(跟上面步骤 2 的请求不是同一次请求,因此密钥不同,加密解密数据不同)

在这里插入图片描述

在这里插入图片描述

(完)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1130829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows环境部署流媒体服务器ZLMediaKit

参考资料 快速开始 ZLMediaKit/ZLMediaKit Wiki GitHub 环境准备 序号名称版本作用下载地址1Microsoft Visual Studio链接:https://pan.baidu.com/s/1DoWjNZ72Y8YpGpSTY0CNKw 提取码:pv6a2opensslWin32/Win64 OpenSSL Installer for Windows - Shi…

聚观早报 | vivo Y100官宣;极氪001 FR将上市

【聚观365】10月25日消息 vivo Y100官宣 一极氪001 FR将上市 特斯拉加速扩张 苹果扩大招聘力度 小米澎湃OS实现历史性跨越 vivo Y100官宣 vivo Y系列是vivo存在比较久的入门系列,主打千元价位的线下市场,在消费者中有着不错的口碑。而不久前一款型…

R语言代码示例

以下是一个使用R语言和httrOAuth库的下载器程序&#xff0c;用于下载的内容。程序使用以下代码。 # 安装和加载必要的库 install.packages("httr") install.packages("httrOAuth") library(httr) library(httrOAuth) ​ # 设置 http_proxy <- "du…

10 个最佳免费 PDF 压缩工具软件

PDF 是一种全球流行的文件格式&#xff0c;可在不损失质量或文本对齐的情况下传输文档。问题是许多文件共享应用程序和网站限制您可以共享或上传的 PDF 的大小。 10 个最佳免费 PDF 压缩工具软件 在这种情况下&#xff0c;您将需要一个可以为您减小 PDF 文件大小的应用程序。P…

Kafka磁盘写满日志清理操作

最近项目组的kafka集群&#xff0c;老是由于应用端写入kafka topic的消息太多&#xff0c;导致所在的broker节点占满&#xff0c;导致其他的组件接连宕机。 这里和应用端沟通可以删除1天之前的消息来清理磁盘&#xff0c;并且可以调整topic的消息存活时间。 一、调整Topic的消…

手写 Promise(2)实例方法与静态方法的实现

一&#xff1a;什么是 Promise Promise 是异步编程的一种解决方案&#xff0c;其实是一个构造函数&#xff0c;自己身上有all、reject、resolve这几个方法&#xff0c;原型上有then、catch等方法。 Promise对象有以下两个特点。 &#xff08;1&#xff09;对象的状态不受…

[③ADRV902x]: Digital Filter Configuration(接收端)

前言 本篇博客主要总结了ADRV9029 Rx接收端链路中各个滤波器的配置。配置不同的滤波器系数以及不同的参数&#xff0c;可以对输入的数字信号灵活得做decimation处理&#xff0c;decimation信号抽取&#xff0c;就是降低信号采样率的过程。 Receiver Signal Path 下图为接收端…

macbook2024免费mac系统优化清理软件CleanMyMac X

清理电脑的操作系统可能是我们一直以来的习惯&#xff0c;从windows系统到mac系统&#xff0c;我们一直在寻求最好的清理方法&#xff0c;能够有效地清理操作系统对于电脑来说是非常重要的。今天小编想和大家一起讨论使用在macbook上的清理软件&#xff0c;清理macbook的空间可…

在React中,什么是状态(state)?如何更新组件的状态?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

C语言程序设计——输入三个整数x,y,z,请把这三个数由小到大输出

题目&#xff1a;输入三个整数x,y,z&#xff0c;请把这三个数由小到大输出。 程序分析&#xff1a;我们想办法把最小的数放到x上&#xff0c;先将x与y进行比较&#xff0c; 如果x>y则将x与y的值进行交换&#xff0c;然后再用x与z进行比较&#xff0c;如果x>z则将x与z的值…

谈谈Net-SNMP软件

Net-SNMP是一个开源的SNMP软件套件&#xff0c;它提供了SNMP代理&#xff08;snmpd&#xff09;和SNMP工具&#xff08;如snmpget、snmpwalk等&#xff09;&#xff0c;可以用于监控和管理网络设备。 Net-SNMP最初是从UC Davis的SNMP软件衍生而来&#xff0c;现在已经成为广泛…

SpringAOP源码解析之advice构建排序(二)

上一章我们知道Spring开启AOP之后会注册AnnotationAwareAspectJAutoProxyCreator类的定义信息&#xff0c;所以在属性注入之后initializeBean的applyBeanPostProcessorsAfterInitialization方法执行的时候调用AnnotationAwareAspectJAutoProxyCreator父类(AbstractAutoProxyCre…

通过怪物展示Demo理解游戏设计模式中的迭代器模式

点击上方亿元程序员关注和★星标 引言 大家好&#xff0c;我是亿元程序员&#xff0c;一位有着8年游戏行业经验的主程。 本系列是《和8年游戏主程一起学习设计模式》&#xff0c;让糟糕的代码在潜移默化中升华&#xff0c;欢迎大家关注分享收藏订阅。 今天我们要来聊一聊游戏…

开启生成式AI的探索之旅,亚马逊云科技分享生成式AI热门案例

现今&#xff0c;生成式AI为企业争先讨论的热门话题&#xff0c;上云出海为企业转型的重中之重。无论你是行业新贵还是中小企业&#xff0c;探索新的模式、创新迭代业务都是不容忽视的重点&#xff0c;下面就来介绍几个亚马逊云科技帮助企业创新的案例。 开启生成式AI的探索之旅…

深入理解 MySQL 中的锁和MVCC机制

文章目录 锁&#xff1a;数据访问的保护者1. 了解锁的基本概念2. 锁的使用场景3. 示例&#xff1a;MySQL中的锁 MVCC&#xff1a;多版本并发控制1. MVCC的工作原理2. MVCC的优点3. 示例&#xff1a;MySQL中的MVCC 如何选择合适的锁和MVCC1. 确定隔离级别2. 避免过度使用锁3. 监…

Spring IOC 和 AOP

核心概念 咱们这节就讲完了&#xff0c;在这节中我们讲了两个大概念&#xff0c;一个叫做IOC&#xff0c;一个叫做DI IOC是什么&#xff1f;是用对象的时候不要自己用new而是由外部提供&#xff0c;而spring在进行实现的时候是谁提供&#xff0c;就是IOC容器给你提供。 DI是什…

什么是脚本文件,脚本的执行,脚本格式等

1.脚本文件是什么&#xff1f; 脚本文件是包含一系列计算机命令的文本文件&#xff0c;通常用于自动化任务、自定义功能或执行特定操作。这些命令通常按照一定的编程语法和语义规则编写&#xff0c;以便计算机能够逐行解释和执行它们。脚本文件通常包含了一组操作&#xff0c;…

lua-web-utils和proxy设置示例

以下是一个使用lua-web-utils和proxy的下载器程序&#xff1a; -- 首先安装lua-web-utils库 local lwu require "lwu" ​ -- 获取服务器 local function get_proxy()local proxy_url "duoipget_proxy"local resp, code, headers, err lwu.fetch(proxy_…

工业通信网关常用的工业通信协议

在工业领域中常常有不同的设备协同工作&#xff0c;而这些设备的通信协议和数据格式也有所差异&#xff0c;要想实现不同通信设备之间的数据传输互通&#xff0c;工业网关是一个重要的设备。 什么是工业网关 工业网关是一种能够连接多种不同设备并实现数据的收集、传输、处理和…