一、思路

使用 RSA 秘钥生成工具生成一对公钥 (A) 和私钥(B),前端保留 A,后端保留 B。

前端发送数据时,先生成一串随机 16 位字符串作为 AES 的秘钥 (C),然后使用 A 使用 RSA 算法对 C 进行加密,得到加密后的 AES 秘钥(D)。将要发送的数据(E) 用 C 使用 AES 加密,得到密文(F)。将 D 和 F 一同发给后端进行处理。

后端处理数据时,先用 B 对 D 使用 RSA 进行解密得到 C,用 C 对 F 使用 AES 进行解密得到 E,处理后得到结果 G,再用 C 对 G 进行 AES 加密得到 H,将 H 返回给前端。

前端接收到 H 后用 C 进行解密,得到处理的结果 G。

因为对数据进行加密的 AES 秘钥是每次请求随机生成的,而且传输过程中 AES 是使用非对称加密的,只要后端持有的 RSA 私钥不泄露即可保证数据通信安全。

图 2 后端加解密数据流图

图 1 前端加解密数据流图

二、前端组件的使用

1、引入插件

① 引入 AES 对称加密插件

npm i —save crypto-js

② 引入 RSA 非对称插件

npm i —save jsencrypt

2、新建 encrypt.js 页面进行封装 及使用

Encrypt.js 封装导出内容如图:

使用

AES 加密

使用 Encrypt() 方法进行加密,传入两个参数:encrypted 和 key,key 是随机生成的 16 位字符串,encrypted 为需要加密的内容,最后 return 出加密结果

AES 解密

使用 Decrypt() 方法进行解密,传参:data 和 key,key 为随机生成的 16 位字符串 (同加密时的 key 一致),data 为后端返回 AES 加密字段,return 解密 string 类型结果

RSA 加密

encryptRsa() 方法进行加密,根据后端提供公钥与随机生成的 key 值进行加密,输出加密结果

三、后端模块的使用

1. 使用

使用 @Decrypt 注解进行解密,使用 @Encrypt 注解进行加密,其中 value 属性写入需要加解密的字段 (以 EL 的形式),其中若需要对方法返回值加解密,需要 @{return} 的方式。type 属性指出需要哪种加解密方法。

如图,需要对 getUser() 方法的 s 参数进行解密,对返回值进行加密,加密方式为 EncryptType.Controller_RSA_AES。

2. 新增 / 修改加密方式

在枚举类 EncryptType 中添加新的枚举方法即可

枚举类中有三个抽象方法:encrypt()、decrypt()、getKey(),新增的枚举需要实现这三个方法。

对注解的拦截是 DecryptAspect 和 EncryptAspect 类,这是两个切面。拦截两个注解标注的方法后将 value 值交给 SPEL 解析器解析后修改对应的值。