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

前言

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

本文来简单分析一下框架中请求加密的实现方式。该功能来源于框架 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 的请求不是同一次请求,因此密钥不同,加密解密数据不同)

在这里插入图片描述

在这里插入图片描述

(完)

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MichelleChung

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值