最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

【RuoYi

运维笔记admin34浏览0评论

【RuoYi

【RuoYi

文章目录

    • 前言
    • 框架版本
      • 前端
      • 服务端
    • 框架集成
      • 前端集成
      • 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.dromaramon.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.dromaramon.core.constant.Constants;
import org.dromaramon.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);}@Overridepublic BufferedReader getReader() {return new BufferedReader(new InputStreamReader(getInputStream()));}@Overridepublic int getContentLength() {return body.length;}@Overridepublic long getContentLengthLong() {return body.length;}@Overridepublic String getContentType() {return MediaType.APPLICATION_JSON_VALUE;}@Overridepublic ServletInputStream getInputStream() {final ByteArrayInputStream bais = new ByteArrayInputStream(body);return new ServletInputStream() {@Overridepublic int read() {return bais.read();}@Overridepublic int available() {return body.length;}@Overridepublic boolean isFinished() {return false;}@Overridepublic boolean isReady() {return false;}@Overridepublic void setReadListener(ReadListener readListener) {}};}
}

2.5、加解密工具类 EncryptUtils

EncryptUtils#decryptByRsa

EncryptUtils#decryptByBase64

EncryptUtils#decryptByAes

2.6、自动装配 ApiDecryptAutoConfiguration

请求测试

1、测试方法

登录: [POST] /auth/login

2、输出

对解密信息输出一下:

3、Debug

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

(完)

发布评论

评论列表(0)

  1. 暂无评论