diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 6c1fa63e2..4f3da2c5f 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -179,19 +179,20 @@ mybatis-plus: updateStrategy: NOT_NULL # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件 where-strategy: NOT_NULL + # 数据加密 mybatis-encryptor: # 是否开启加密 - enabled: false + enable: false # 默认加密算法 - algorithm: base64 - # 安全秘钥。对称算法的秘钥。如:AES,SM4 -# password: QBcc3SHK2G4ijyfl5XQ7@2g!N2j2jRDR -# # 公私钥。非对称算法的公私钥,如:SM2,RSA -# publicKey: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCDt41GIcWvY6/tpjOLoWY78Oy00uWcNbMRG/8DRoS79/h2D+pV8uxV+0ezaN+fBFCZnK8TdJcPeU4EnNRUh/8HEY33KFvZ700n+Gj5BHUUDKzx3UVFNuF49UI/yoJ8rz6VQQHO79KK89VwmSMO77Tfee1ofe0STY6IwMt/MwaoKwIDAQAB -# privateKey: MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIO3jUYhxa9jr+2mM4uhZjvw7LTS5Zw1sxEb/wNGhLv3+HYP6lXy7FX7R7No358EUJmcrxN0lw95TgSc1FSH/wcRjfcoW9nvTSf4aPkEdRQMrPHdRUU24Xj1Qj/KgnyvPpVBAc7v0orz1XCZIw7vtN957Wh97RJNjojAy38zBqgrAgMBAAECgYAkXx4qvI6rFNryw88+Am6JpMioUghHb2ioE9QCYomqohnA+DocS71JLN8qwo3lijp7gJGzzKEeC8Aoc+oKAZfBQQwPP0K/ql+NcLdlqNAr+XyzkZrLJD/BfluQ6mXI23tjonWnPPZ1Et9HC3zXRQPiuh7Ff6UoqatTMI3OIbSyuQJBAPbaJpVYmIsWJdpvaAC6hcGgR/vbG9yX8VphPn8/2wsm2MmQrRkUoKkudE/veX3KQjGikDwo9+bT6aBl+nn2DUUCQQCImSGZFNcGqhMLyRGVogP6fh0YZSEQAhFbZ69nQmplqbie+dREhODH5Vs5F0C2aL5iSR/UaIDkNEA1auX7x56vAkAFWjON927PTTqi4tmBconl6eDFsDmJbe34xLUDM1I/iqcWr8FhEtZs9Knm9c1PkewfgWPZOhYt9hhRtwRYUqJ1AkAPvQ0I9US9KNVe80DKa8tnjiZODEDd9k8HqA+mpxlZM0/pSUGyz1iSz5NOJaa4HaNp8aDwOUY4hOis/u8Wrm5TAkEA00YeUsaXlMyMF/5pjols44tXb54AjAC2mH66pz9JsKg7pKpWVOpEV5rMY58CGZHWau69vGLZnCd1coeMw77YAQ== -# # 编码方式,base64/hex。默认base64 -# encode: base64 + algorithm: BASE64 + # 编码方式 BASE64/HEX。默认BASE64 + encode: BASE64 + # 安全秘钥 对称算法的秘钥 如:AES,SM4 + password: + # 公私钥 非对称算法的公私钥 如:SM2,RSA + publicKey: + privateKey: # Swagger配置 swagger: diff --git a/ruoyi-admin/src/test/java/com/ruoyi/test/EncryptUnitTest.java b/ruoyi-admin/src/test/java/com/ruoyi/test/EncryptUnitTest.java deleted file mode 100644 index b049232ab..000000000 --- a/ruoyi-admin/src/test/java/com/ruoyi/test/EncryptUnitTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.ruoyi.test; - -import cn.dev33.satoken.annotation.SaIgnore; -import com.ruoyi.demo.domain.TestDemo; -import com.ruoyi.demo.mapper.TestDemoMapper; -import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; - -import javax.annotation.Resource; - -/** - * 加密单元测试案例 - * - * @author 老马 - * @date 2023-01-12 08:53 - */ -@SpringBootTest -@SaIgnore -@DisplayName("加密测试") -public class EncryptUnitTest { - - @Resource - private TestDemoMapper demoMapper; - - @Test - public void testCrypt() { - TestDemo demo = new TestDemo(); - demo.setTestKey("测试的key"); - demo.setValue("测试的value"); - this.demoMapper.insert(demo); - System.out.println(demo); - TestDemo testDemo = this.demoMapper.selectById(demo.getId()); - System.out.println(testDemo); - } - -} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/EncryptField.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/EncryptField.java index d44eb293c..2d6a321f1 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/EncryptField.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/EncryptField.java @@ -19,7 +19,7 @@ public @interface EncryptField { /** * 加密算法 */ - AlgorithmType algorithm() default AlgorithmType.BASE64; + AlgorithmType algorithm() default AlgorithmType.DEFAULT; /** * 秘钥。AES、SM4需要 @@ -39,6 +39,6 @@ public @interface EncryptField { /** * 编码方式。对加密算法为BASE64的不起作用 */ - EncodeType encode() default EncodeType.BASE64; + EncodeType encode() default EncodeType.DEFAULT; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptContext.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptContext.java index 3340ecdc1..1b82d51bd 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptContext.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptContext.java @@ -1,18 +1,23 @@ package com.ruoyi.common.encrypt; +import com.ruoyi.common.enums.AlgorithmType; import com.ruoyi.common.enums.EncodeType; -import lombok.Builder; import lombok.Data; /** - * 加密上下文。用于encryptor传递必要的参数。 - * 隔离配置和注解 + * 加密上下文 用于encryptor传递必要的参数。 * * @author 老马 - * @date 2023-01-17 08:31 + * @version 4.6.0 */ @Data public class EncryptContext { + + /** + * 默认算法 + */ + private AlgorithmType algorithm; + /** * 安全秘钥 */ @@ -32,4 +37,5 @@ public class EncryptContext { * 编码方式,base64/hex */ private EncodeType encode; + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java index fae0327c1..7986a9b79 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java @@ -7,16 +7,12 @@ import com.ruoyi.common.enums.EncodeType; * 加解者 * * @author 老马 - * @date 2023-01-10 16:08 + * @version 4.6.0 */ public interface IEncryptor { /** * 获得当前算法 - * - * @return com.ruoyi.common.enums.AlgorithmType - * @author 老马 - * @date 2023/1/11 11:18 */ AlgorithmType algorithm(); @@ -25,22 +21,15 @@ public interface IEncryptor { * * @param value 待加密字符串 * @param encodeType 加密后的编码格式 - * @return java.lang.String 加密后的字符串 - * @throws Exception 抛出异常 - * @author 老马 - * @date 2023/1/10 16:38 + * @return 加密后的字符串 */ - String encrypt(String value, EncodeType encodeType) throws Exception; + String encrypt(String value, EncodeType encodeType); /** * 解密 * * @param value 待加密字符串 - * @param encodeType 加密后的编码格式 - * @return java.lang.String 解密后的字符串 - * @throws Exception 抛出异常 - * @author 老马 - * @date 2023/1/10 16:38 + * @return 解密后的字符串 */ - String decrypt(String value, EncodeType encodeType) throws Exception; + String decrypt(String value); } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AbstractEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AbstractEncryptor.java index 5e7ce73d0..860533612 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AbstractEncryptor.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AbstractEncryptor.java @@ -7,10 +7,12 @@ import com.ruoyi.common.encrypt.IEncryptor; * 所有加密执行者的基类 * * @author 老马 - * @date 2023-01-17 16:52 + * @version 4.6.0 */ public abstract class AbstractEncryptor implements IEncryptor { + public AbstractEncryptor(EncryptContext context) { - //子类必须实现带参数的构造方法 + // 用户配置校验与配置注入 } + } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AesEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AesEncryptor.java index f0d3a3069..ee4d82665 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AesEncryptor.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/AesEncryptor.java @@ -1,7 +1,6 @@ package com.ruoyi.common.encrypt.encryptor; import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.symmetric.AES; @@ -15,32 +14,28 @@ import java.nio.charset.StandardCharsets; * AES算法实现 * * @author 老马 - * @date 2023-01-06 11:39 + * @version 4.6.0 */ public class AesEncryptor extends AbstractEncryptor { - private AES aes = null; + private final AES aes; public AesEncryptor(EncryptContext context) { super(context); String password = context.getPassword(); if (StrUtil.isBlank(password)) { - throw new RuntimeException("aes没有获得秘钥信息"); + throw new IllegalArgumentException("AES没有获得秘钥信息"); } // aes算法的秘钥要求是16位、24位、32位 int[] array = {16, 24, 32}; - if(!ArrayUtil.contains(array, password.length())) { - throw new RuntimeException("aes秘钥长度应该为16位、24位、32位,实际为"+password.length()+"位"); + if (!ArrayUtil.contains(array, password.length())) { + throw new IllegalArgumentException("AES秘钥长度应该为16位、24位、32位,实际为" + password.length() + "位"); } aes = SecureUtil.aes(context.getPassword().getBytes(StandardCharsets.UTF_8)); } /** * 获得当前算法 - * - * @return com.ruoyi.common.enums.AlgorithmType - * @author 老马 - * @date 2023/1/11 11:18 */ @Override public AlgorithmType algorithm() { @@ -52,36 +47,23 @@ public class AesEncryptor extends AbstractEncryptor { * * @param value 待加密字符串 * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String encrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.aes)) { - if (encodeType == EncodeType.HEX) { - return aes.encryptHex(value); - } else { - return aes.encryptBase64(value); - } + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return aes.encryptHex(value); + } else { + return aes.encryptBase64(value); } - return value; } /** * 解密 * * @param value 待加密字符串 - * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String decrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.aes)) { - return this.aes.decryptStr(value); - } - return value; + public String decrypt(String value) { + return this.aes.decryptStr(value); } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Base64Encryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Base64Encryptor.java index bd5038e4b..519158d00 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Base64Encryptor.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Base64Encryptor.java @@ -6,10 +6,10 @@ import com.ruoyi.common.enums.AlgorithmType; import com.ruoyi.common.enums.EncodeType; /** - * Base64算法实现。不建议在生产环境使用 + * Base64算法实现 * * @author 老马 - * @date 2023-01-06 10:00 + * @version 4.6.0 */ public class Base64Encryptor extends AbstractEncryptor { @@ -19,10 +19,6 @@ public class Base64Encryptor extends AbstractEncryptor { /** * 获得当前算法 - * - * @return com.ruoyi.common.enums.AlgorithmType - * @author 老马 - * @date 2023/1/11 11:18 */ @Override public AlgorithmType algorithm() { @@ -34,12 +30,9 @@ public class Base64Encryptor extends AbstractEncryptor { * * @param value 待加密字符串 * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String encrypt(String value, EncodeType encodeType) throws Exception { + public String encrypt(String value, EncodeType encodeType) { return Base64.encode(value); } @@ -47,13 +40,9 @@ public class Base64Encryptor extends AbstractEncryptor { * 解密 * * @param value 待加密字符串 - * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String decrypt(String value, EncodeType encodeType) throws Exception { + public String decrypt(String value) { return Base64.decodeStr(value); } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/RsaEncryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/RsaEncryptor.java index 40d767c06..2563fc214 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/RsaEncryptor.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/RsaEncryptor.java @@ -1,7 +1,6 @@ package com.ruoyi.common.encrypt.encryptor; import cn.hutool.core.codec.Base64; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.RSA; @@ -15,28 +14,24 @@ import com.ruoyi.common.utils.StringUtils; * RSA算法实现 * * @author 老马 - * @date 2023-01-06 09:37 + * @version 4.6.0 */ public class RsaEncryptor extends AbstractEncryptor { - private RSA rsa = null; + private final RSA rsa; public RsaEncryptor(EncryptContext context) { super(context); String privateKey = context.getPrivateKey(); String publicKey = context.getPublicKey(); if (StringUtils.isAnyEmpty(privateKey, publicKey)) { - throw new RuntimeException("rsa公私钥均需要提供,公钥加密,私钥解密。"); + throw new IllegalArgumentException("RSA公私钥均需要提供,公钥加密,私钥解密。"); } this.rsa = SecureUtil.rsa(Base64.decode(privateKey), Base64.decode(publicKey)); } /** * 获得当前算法 - * - * @return com.ruoyi.common.enums.AlgorithmType - * @author 老马 - * @date 2023/1/11 11:18 */ @Override public AlgorithmType algorithm() { @@ -48,36 +43,23 @@ public class RsaEncryptor extends AbstractEncryptor { * * @param value 待加密字符串 * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String encrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.rsa)) { - if (encodeType == EncodeType.HEX) { - return rsa.encryptHex(value, KeyType.PublicKey); - } else { - return rsa.encryptBase64(value, KeyType.PublicKey); - } + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return rsa.encryptHex(value, KeyType.PublicKey); + } else { + return rsa.encryptBase64(value, KeyType.PublicKey); } - return value; } /** * 解密 * * @param value 待加密字符串 - * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String decrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.rsa)) { - return this.rsa.decryptStr(value, KeyType.PrivateKey); - } - return value; + public String decrypt(String value) { + return this.rsa.decryptStr(value, KeyType.PrivateKey); } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm2Encryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm2Encryptor.java index 71f0620ca..a84f7f7ea 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm2Encryptor.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm2Encryptor.java @@ -2,7 +2,6 @@ package com.ruoyi.common.encrypt.encryptor; import cn.hutool.core.codec.Base64; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.asymmetric.KeyType; import cn.hutool.crypto.asymmetric.SM2; @@ -15,28 +14,24 @@ import com.ruoyi.common.utils.StringUtils; * sm2算法实现 * * @author 老马 - * @date 2023-01-06 17:13 + * @version 4.6.0 */ public class Sm2Encryptor extends AbstractEncryptor { - private SM2 sm2 = null; + private final SM2 sm2; public Sm2Encryptor(EncryptContext context) { super(context); String privateKey = context.getPrivateKey(); String publicKey = context.getPublicKey(); if (StringUtils.isAnyEmpty(privateKey, publicKey)) { - throw new RuntimeException("sm2公私钥均需要提供,公钥加密,私钥解密。"); + throw new IllegalArgumentException("SM2公私钥均需要提供,公钥加密,私钥解密。"); } this.sm2 = SmUtil.sm2(Base64.decode(privateKey), Base64.decode(publicKey)); } /** * 获得当前算法 - * - * @return com.ruoyi.common.enums.AlgorithmType - * @author 老马 - * @date 2023/1/11 11:18 */ @Override public AlgorithmType algorithm() { @@ -48,38 +43,23 @@ public class Sm2Encryptor extends AbstractEncryptor { * * @param value 待加密字符串 * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @throws Exception 抛出异常 - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String encrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.sm2)) { - if (encodeType == EncodeType.HEX) { - return sm2.encryptHex(value, KeyType.PublicKey); - } else { - return sm2.encryptBase64(value, KeyType.PublicKey); - } + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return sm2.encryptHex(value, KeyType.PublicKey); + } else { + return sm2.encryptBase64(value, KeyType.PublicKey); } - return value; } /** * 解密 * * @param value 待加密字符串 - * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @throws Exception 抛出异常 - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String decrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.sm2)) { - return this.sm2.decryptStr(value, KeyType.PrivateKey); - } - return value; + public String decrypt(String value) { + return this.sm2.decryptStr(value, KeyType.PrivateKey); } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm4Encryptor.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm4Encryptor.java index f30afdce6..7d2e50974 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm4Encryptor.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/encryptor/Sm4Encryptor.java @@ -1,6 +1,5 @@ package com.ruoyi.common.encrypt.encryptor; -import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.crypto.SmUtil; import cn.hutool.crypto.symmetric.SM4; @@ -14,31 +13,27 @@ import java.nio.charset.StandardCharsets; * sm4算法实现 * * @author 老马 - * @date 2023-01-06 17:40 + * @version 4.6.0 */ public class Sm4Encryptor extends AbstractEncryptor { - private SM4 sm4 = null; + private final SM4 sm4; public Sm4Encryptor(EncryptContext context) { super(context); String password = context.getPassword(); if (StrUtil.isBlank(password)) { - throw new RuntimeException("sm4没有获得秘钥信息"); + throw new IllegalArgumentException("SM4没有获得秘钥信息"); } // sm4算法的秘钥要求是16位长度 if (16 != password.length()) { - throw new RuntimeException("sm4秘钥长度应该为16位,实际为" + password.length() + "位"); + throw new IllegalArgumentException("SM4秘钥长度应该为16位,实际为" + password.length() + "位"); } this.sm4 = SmUtil.sm4(password.getBytes(StandardCharsets.UTF_8)); } /** * 获得当前算法 - * - * @return com.ruoyi.common.enums.AlgorithmType - * @author 老马 - * @date 2023/1/11 11:18 */ @Override public AlgorithmType algorithm() { @@ -50,38 +45,23 @@ public class Sm4Encryptor extends AbstractEncryptor { * * @param value 待加密字符串 * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @throws Exception 抛出异常 - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String encrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.sm4)) { - if (encodeType == EncodeType.HEX) { - return sm4.encryptHex(value); - } else { - return sm4.encryptBase64(value); - } + public String encrypt(String value, EncodeType encodeType) { + if (encodeType == EncodeType.HEX) { + return sm4.encryptHex(value); + } else { + return sm4.encryptBase64(value); } - return value; } /** * 解密 * * @param value 待加密字符串 - * @param encodeType 加密后的编码格式 - * @return java.lang.String - * @throws Exception 抛出异常 - * @author 老马 - * @date 2023/1/10 16:38 */ @Override - public String decrypt(String value, EncodeType encodeType) throws Exception { - if (ObjectUtil.isNotNull(this.sm4)) { - return this.sm4.decryptStr(value); - } - return value; + public String decrypt(String value) { + return this.sm4.decryptStr(value); } } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java index eb9b830a0..124a139da 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java @@ -1,6 +1,5 @@ package com.ruoyi.common.enums; -import com.ruoyi.common.encrypt.IEncryptor; import com.ruoyi.common.encrypt.encryptor.*; import lombok.AllArgsConstructor; import lombok.Getter; @@ -9,10 +8,17 @@ import lombok.Getter; * 算法名称 * * @author 老马 + * @version 4.6.0 */ @Getter @AllArgsConstructor public enum AlgorithmType { + + /** + * 默认走yml配置 + */ + DEFAULT(null), + /** * base64 */ @@ -38,5 +44,5 @@ public enum AlgorithmType { */ SM4(Sm4Encryptor.class); - private final Class clazz; + private final Class clazz; } diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/EncodeType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EncodeType.java index 24cdab63a..4d469597c 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/enums/EncodeType.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/EncodeType.java @@ -4,9 +4,15 @@ package com.ruoyi.common.enums; * 编码类型 * * @author 老马 - * @date 2023-01-11 11:39 + * @version 4.6.0 */ public enum EncodeType { + + /** + * 默认使用yml配置 + */ + DEFAULT, + /** * base64编码 */ diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptController.java new file mode 100644 index 000000000..6abe4e184 --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptController.java @@ -0,0 +1,55 @@ +package com.ruoyi.demo.controller; + +import com.ruoyi.common.core.domain.R; +import com.ruoyi.demo.domain.TestDemoEncrypt; +import com.ruoyi.demo.mapper.TestDemoEncryptMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + + +/** + * 测试数据库加解密功能 + * + * @author Lion Li + */ +@Validated +@RestController +@RequestMapping("/demo/encrypt") +public class TestEncryptController { + + @Autowired + private TestDemoEncryptMapper mapper; + @Value("${mybatis-encryptor.enable}") + private Boolean encryptEnable; + + /** + * 测试数据库加解密 + * + * @param key 测试key + * @param value 测试value + */ + @GetMapping() + public R> test(String key, String value) { + if (!encryptEnable) { + throw new RuntimeException("加密功能未开启!"); + } + Map map = new HashMap<>(2); + TestDemoEncrypt demo = new TestDemoEncrypt(); + demo.setTestKey(key); + demo.setValue(value); + mapper.insert(demo); + map.put("加密", demo); + TestDemoEncrypt testDemo = mapper.selectById(demo.getId()); + map.put("解密", testDemo); + return R.ok(map); + } + + +} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java index e32843a44..dc19ce2c7 100644 --- a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemo.java @@ -1,9 +1,7 @@ package com.ruoyi.demo.domain; import com.baomidou.mybatisplus.annotation.*; -import com.ruoyi.common.annotation.EncryptField; import com.ruoyi.common.core.domain.BaseEntity; -import com.ruoyi.common.enums.AlgorithmType; import lombok.Data; import lombok.EqualsAndHashCode; @@ -46,15 +44,11 @@ public class TestDemo extends BaseEntity { /** * key键 */ -// @EncryptField(algorithm=AlgorithmType.SM2, privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgZSlOvw8FBiH+aFJWLYZP/VRjg9wjfRarTkGBZd/T3N+gCgYIKoEcz1UBgi2hRANCAAR5DGuQwJqkxnbCsP+iPSDoHWIF4RwcR5EsSvT8QPxO1wRkR2IhCkzvRb32x2CUgJFdvoqVqfApFDPZzShqzBwX", publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEeQxrkMCapMZ2wrD/oj0g6B1iBeEcHEeRLEr0/ED8TtcEZEdiIQpM70W99sdglICRXb6KlanwKRQz2c0oaswcFw==") - @EncryptField(algorithm = AlgorithmType.RSA, privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANBBEeueWlXlkkj2+WY5l+IWe42d8b5K28g+G/CFKC/yYAEHtqGlCsBOrb+YBkG9mPzmuYA/n9k0NFIc8E8yY5vZQaroyFBrTTWEzG9RY2f7Y3svVyybs6jpXSUs4xff8abo7wL1Y/wUaeatTViamxYnyTvdTmLm3d+JjRij68rxAgMBAAECgYAB0TnhXraSopwIVRfmboea1b0upl+BUdTJcmci412UjrKr5aE695ZLPkXbFXijVu7HJlyyv94NVUdaMACV7Ku/S2RuNB70M7YJm8rAjHFC3/i2ZeIM60h1Ziy4QKv0XM3pRATlDCDNhC1WUrtQCQSgU8kcp6eUUppruOqDzcY04QJBAPm9+sBP9CwDRgy3e5+V8aZtJkwDstb0lVVV/KY890cydVxiCwvX3fqVnxKMlb+x0YtH0sb9v+71xvK2lGobaRECQQDVePU6r/cCEfpc+nkWF6osAH1f8Mux3rYv2DoBGvaPzV2BGfsLed4neRfCwWNCKvGPCdW+L0xMJg8+RwaoBUPhAkAT5kViqXxFPYWJYd1h2+rDXhMdH3ZSlm6HvDBDdrwlWinr0Iwcx3iSjPV93uHXwm118aUj4fg3LDJMCKxOwBxhAkByrQXfvwOMYygBprRBf/j0plazoWFrbd6lGR0f1uI5IfNnFRPdeFw1DEINZ2Hw+6zEUF44SqRMC+4IYJNc02dBAkBCgy7RvfyV/A7N6kKXxTHauY0v6XwSSvpeKtRJkbIcRWOdIYvaHO9L7cklj3vIEdwjSUp9K4VTBYYlmAz1xh03", publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQQRHrnlpV5ZJI9vlmOZfiFnuNnfG+StvIPhvwhSgv8mABB7ahpQrATq2/mAZBvZj85rmAP5/ZNDRSHPBPMmOb2UGq6MhQa001hMxvUWNn+2N7L1csm7Oo6V0lLOMX3/Gm6O8C9WP8FGnmrU1YmpsWJ8k73U5i5t3fiY0Yo+vK8QIDAQAB") private String testKey; /** * 值 */ - //@EncryptField(algorithm = AlgorithmType.SM4, password = "10rfylhtccpuyke5") - @EncryptField(algorithm = AlgorithmType.AES, password = "10rfylhtccpuyke5") private String value; /** diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemoEncrypt.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemoEncrypt.java new file mode 100644 index 000000000..4672185c7 --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/domain/TestDemoEncrypt.java @@ -0,0 +1,29 @@ +package com.ruoyi.demo.domain; + +import com.baomidou.mybatisplus.annotation.TableName; +import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.enums.AlgorithmType; +import lombok.Data; +import lombok.EqualsAndHashCode; + +@Data +@EqualsAndHashCode(callSuper = true) +@TableName("test_demo") +public class TestDemoEncrypt extends TestDemo { + + /** + * key键 + */ + // @EncryptField(algorithm=AlgorithmType.SM2, privateKey = "MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgZSlOvw8FBiH+aFJWLYZP/VRjg9wjfRarTkGBZd/T3N+gCgYIKoEcz1UBgi2hRANCAAR5DGuQwJqkxnbCsP+iPSDoHWIF4RwcR5EsSvT8QPxO1wRkR2IhCkzvRb32x2CUgJFdvoqVqfApFDPZzShqzBwX", publicKey = "MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAEeQxrkMCapMZ2wrD/oj0g6B1iBeEcHEeRLEr0/ED8TtcEZEdiIQpM70W99sdglICRXb6KlanwKRQz2c0oaswcFw==") + @EncryptField(algorithm = AlgorithmType.RSA, privateKey = "MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBANBBEeueWlXlkkj2+WY5l+IWe42d8b5K28g+G/CFKC/yYAEHtqGlCsBOrb+YBkG9mPzmuYA/n9k0NFIc8E8yY5vZQaroyFBrTTWEzG9RY2f7Y3svVyybs6jpXSUs4xff8abo7wL1Y/wUaeatTViamxYnyTvdTmLm3d+JjRij68rxAgMBAAECgYAB0TnhXraSopwIVRfmboea1b0upl+BUdTJcmci412UjrKr5aE695ZLPkXbFXijVu7HJlyyv94NVUdaMACV7Ku/S2RuNB70M7YJm8rAjHFC3/i2ZeIM60h1Ziy4QKv0XM3pRATlDCDNhC1WUrtQCQSgU8kcp6eUUppruOqDzcY04QJBAPm9+sBP9CwDRgy3e5+V8aZtJkwDstb0lVVV/KY890cydVxiCwvX3fqVnxKMlb+x0YtH0sb9v+71xvK2lGobaRECQQDVePU6r/cCEfpc+nkWF6osAH1f8Mux3rYv2DoBGvaPzV2BGfsLed4neRfCwWNCKvGPCdW+L0xMJg8+RwaoBUPhAkAT5kViqXxFPYWJYd1h2+rDXhMdH3ZSlm6HvDBDdrwlWinr0Iwcx3iSjPV93uHXwm118aUj4fg3LDJMCKxOwBxhAkByrQXfvwOMYygBprRBf/j0plazoWFrbd6lGR0f1uI5IfNnFRPdeFw1DEINZ2Hw+6zEUF44SqRMC+4IYJNc02dBAkBCgy7RvfyV/A7N6kKXxTHauY0v6XwSSvpeKtRJkbIcRWOdIYvaHO9L7cklj3vIEdwjSUp9K4VTBYYlmAz1xh03", publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDQQRHrnlpV5ZJI9vlmOZfiFnuNnfG+StvIPhvwhSgv8mABB7ahpQrATq2/mAZBvZj85rmAP5/ZNDRSHPBPMmOb2UGq6MhQa001hMxvUWNn+2N7L1csm7Oo6V0lLOMX3/Gm6O8C9WP8FGnmrU1YmpsWJ8k73U5i5t3fiY0Yo+vK8QIDAQAB") + private String testKey; + + /** + * 值 + */ + // @EncryptField // 什么也不写走默认yml配置 + // @EncryptField(algorithm = AlgorithmType.SM4, password = "10rfylhtccpuyke5") + @EncryptField(algorithm = AlgorithmType.AES, password = "10rfylhtccpuyke5") + private String value; + +} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoEncryptMapper.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoEncryptMapper.java new file mode 100644 index 000000000..5c76097df --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/mapper/TestDemoEncryptMapper.java @@ -0,0 +1,13 @@ +package com.ruoyi.demo.mapper; + +import com.ruoyi.common.core.mapper.BaseMapperPlus; +import com.ruoyi.demo.domain.TestDemoEncrypt; + +/** + * 测试加密功能 + * + * @author Lion Li + */ +public interface TestDemoEncryptMapper extends BaseMapperPlus { + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/EncryptorConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/EncryptorConfig.java index 7d5d21a76..ed90d2067 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/EncryptorConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/EncryptorConfig.java @@ -1,9 +1,10 @@ package com.ruoyi.framework.config; import com.ruoyi.framework.config.properties.EncryptorProperties; -import com.ruoyi.framework.encrypt.EncryptorManager; +import com.ruoyi.framework.manager.EncryptorManager; import com.ruoyi.framework.encrypt.MybatisDecryptInterceptor; import com.ruoyi.framework.encrypt.MybatisEncryptInterceptor; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -12,26 +13,27 @@ import org.springframework.context.annotation.Configuration; * 加解密配置 * * @author 老马 - * @date 2023-01-11 10:03 + * @version 4.6.0 */ @Configuration -@ConditionalOnProperty(value = "mybatis-encryptor.enabled", havingValue = "true") +@ConditionalOnProperty(value = "mybatis-encryptor.enable", havingValue = "true") public class EncryptorConfig { + @Autowired + private EncryptorProperties properties; + @Bean - public EncryptorManager mybatisCryptHandler(EncryptorProperties properties) { - EncryptorManager encryptorManager = new EncryptorManager(); - encryptorManager.registAndGetEncryptor(properties); - return encryptorManager; + public EncryptorManager encryptorManager() { + return new EncryptorManager(); } @Bean - public MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorProperties properties) { - return new MybatisEncryptInterceptor(); + public MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorManager encryptorManager) { + return new MybatisEncryptInterceptor(encryptorManager, properties); } @Bean - public MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorProperties properties) { - return new MybatisDecryptInterceptor(); + public MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorManager encryptorManager) { + return new MybatisDecryptInterceptor(encryptorManager, properties); } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptorProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptorProperties.java index d34949d37..8b2000d6a 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptorProperties.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptorProperties.java @@ -10,7 +10,7 @@ import org.springframework.stereotype.Component; * 加解密属性配置类 * * @author 老马 - * @date 2023-01-10 16:52 + * @version 4.6.0 */ @Data @Component @@ -20,7 +20,7 @@ public class EncryptorProperties { /** * 过滤开关 */ - private Boolean enabled; + private Boolean enable; /** * 默认算法 @@ -46,4 +46,5 @@ public class EncryptorProperties { * 编码方式,base64/hex */ private EncodeType encode; + } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptedFieldsCache.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptedFieldsCache.java deleted file mode 100644 index e9d2a68ab..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptedFieldsCache.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.ruoyi.framework.encrypt; - -import com.ruoyi.common.annotation.EncryptField; - -import java.lang.reflect.Field; -import java.util.Arrays; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; -import java.util.stream.Collectors; - -/** - * 类加密字段缓存类 - * - * @author 老马 - * @date 2023-01-12 11:07 - */ -public class EncryptedFieldsCache { - private static final Map, Set> ENCRYPTED_FIELD_CACHE = new ConcurrentHashMap<>(); - - public static Set get(Class sourceClazz) { - return ENCRYPTED_FIELD_CACHE.computeIfAbsent(sourceClazz, clazz -> { - Field[] declaredFields = clazz.getDeclaredFields(); - Set fieldSet = Arrays.stream(declaredFields).filter(field -> - field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class) - .collect(Collectors.toSet()); - for (Field field : fieldSet) { - field.setAccessible(true); - } - return fieldSet; - }); - } -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptorManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptorManager.java deleted file mode 100644 index d929cc2cd..000000000 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptorManager.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.ruoyi.framework.encrypt; - -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.ReflectUtil; -import com.ruoyi.common.encrypt.EncryptContext; -import com.ruoyi.common.encrypt.IEncryptor; -import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.framework.config.properties.EncryptorProperties; -import lombok.extern.slf4j.Slf4j; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 加密管理类 - * - * @author 老马 - * @date 2023-01-11 10:07 - */ -@Slf4j -public class EncryptorManager { - - /** - * 缓存加密器 - */ - Map encryptorMap = new ConcurrentHashMap<>(); - - - /** - * 注册加密执行者到缓存 - * - * @param properties 加密执行者需要的相关配置参数 - * @author 老马 - * @date 2023/1/11 15:09 - */ - public IEncryptor registAndGetEncryptor(EncryptorProperties properties) { - String encryptorKey = this.getEncryptorKeyFromProperties(properties); - if (encryptorMap.containsKey(encryptorKey)) { - return encryptorMap.get(encryptorKey); - } - EncryptContext encryptContext = new EncryptContext(); - encryptContext.setPassword(properties.getPassword()); - encryptContext.setPrivateKey(properties.getPrivateKey()); - encryptContext.setPublicKey(properties.getPublicKey()); - encryptContext.setEncode(properties.getEncode()); - IEncryptor encryptor = ReflectUtil.newInstance(properties.getAlgorithm().getClazz(), encryptContext); - encryptorMap.put(encryptorKey, encryptor); - return encryptorMap.get(encryptorKey); - } - - /** - * 移除缓存中的加密执行者 - * - * @param properties 加密执行者需要的相关配置参数 - * @author 老马 - * @date 2023/1/11 15:55 - */ - public void removeEncryptor(EncryptorProperties properties) { - this.encryptorMap.remove(getEncryptorKeyFromProperties(properties)); - } - - /** - * 根据配置进行加密。会进行本地缓存对应的算法和对应的秘钥信息。 - * - * @param value 待加密的值 - * @param properties 加密相关的配置信息 - * @return java.lang.String 加密后的结果 - * @author 老马 - * @date 2023/1/11 16:46 - */ - public String encrypt(String value, EncryptorProperties properties) { - try { - IEncryptor encryptor = this.registAndGetEncryptor(properties); - if(ObjectUtil.isNull(encryptor)){ - return value; - } - return encryptor.encrypt(value, properties.getEncode()); - } catch (Exception e) { - log.error("字段加密异常,原样返回", e); - return value; - } - } - - /** - * 根据配置进行解密 - * - * @param value 待解密的值 - * @param properties 加密相关的配置信息 - * @return java.lang.String - * @author 老马 - * @date 2023/1/11 17:43 - */ - public String decrypt(String value, EncryptorProperties properties) { - try { - IEncryptor encryptor = this.registAndGetEncryptor(properties); - if(ObjectUtil.isNull(encryptor)){ - return value; - } - return encryptor.decrypt(value, properties.getEncode()); - } catch (Exception e) { - log.error("字段解密异常,原样返回", e); - return value; - } - } - - - /** - * 从配置内容中提取缓存的KEY - * - * @param properties 加密相关的配置信息 - * @return java.lang.String - * @author 老马 - * @date 2023/1/11 17:39 - */ - private String getEncryptorKeyFromProperties(EncryptorProperties properties) { - return properties.getAlgorithm() + StringUtils.defaultString(properties.getPassword()) + - StringUtils.defaultString(properties.getPublicKey()) + StringUtils.defaultString(properties.getPrivateKey()); - } - -} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisDecryptInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisDecryptInterceptor.java index 1cdb58e1f..c8bbf8f35 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisDecryptInterceptor.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisDecryptInterceptor.java @@ -2,9 +2,13 @@ package com.ruoyi.framework.encrypt; import cn.hutool.core.collection.CollectionUtil; import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.framework.config.properties.EncryptorProperties; +import com.ruoyi.framework.manager.EncryptorManager; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.resultset.ResultSetHandler; import org.apache.ibatis.plugin.*; @@ -20,7 +24,7 @@ import java.util.Set; * 出参解密拦截器 * * @author 老马 - * @date 2023-01-12 13:47 + * @version 4.6.0 */ @Slf4j @Intercepts({@Signature( @@ -28,10 +32,11 @@ import java.util.Set; method = "handleResultSets", args = {Statement.class}) }) +@AllArgsConstructor public class MybatisDecryptInterceptor implements Interceptor { - private final EncryptorManager encryptorManager = SpringUtils.getBean(EncryptorManager.class); - private final EncryptorProperties defaultProperties = SpringUtils.getBean(EncryptorProperties.class); + private final EncryptorManager encryptorManager; + private final EncryptorProperties defaultProperties; @Override public Object intercept(Invocation invocation) throws Throwable { @@ -57,13 +62,13 @@ public class MybatisDecryptInterceptor implements Interceptor { if (sourceObject instanceof List) { // 判断第一个元素是否含有注解。如果没有直接返回,提高效率 Object firstItem = ((List) sourceObject).get(0); - if (CollectionUtil.isEmpty(EncryptedFieldsCache.get(firstItem.getClass()))) { + if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) { return; } ((List) sourceObject).forEach(this::decryptHandler); return; } - Set fields = EncryptedFieldsCache.get(sourceObject.getClass()); + Set fields = encryptorManager.getFieldCache(sourceObject.getClass()); try { for (Field field : fields) { field.set(sourceObject, this.decryptField(String.valueOf(field.get(sourceObject)), field)); @@ -82,15 +87,13 @@ public class MybatisDecryptInterceptor implements Interceptor { */ private String decryptField(String value, Field field) { EncryptField encryptField = field.getAnnotation(EncryptField.class); - EncryptorProperties properties = new EncryptorProperties(); - properties.setEnabled(true); - properties.setAlgorithm(encryptField.algorithm()); - properties.setEncode(encryptField.encode()); - properties.setPassword(StringUtils.isEmpty(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); - properties.setPrivateKey(StringUtils.isEmpty(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); - properties.setPublicKey(StringUtils.isEmpty(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); - this.encryptorManager.registAndGetEncryptor(properties); - return this.encryptorManager.decrypt(value, properties); + EncryptContext encryptContext = new EncryptContext(); + encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm()); + encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode()); + encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); + encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); + encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); + return this.encryptorManager.decrypt(value, encryptContext); } @Override diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisEncryptInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisEncryptInterceptor.java index 4fd5289e0..d9c25bcd3 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisEncryptInterceptor.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/MybatisEncryptInterceptor.java @@ -3,9 +3,13 @@ package com.ruoyi.framework.encrypt; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.enums.EncodeType; import com.ruoyi.common.utils.StringUtils; -import com.ruoyi.common.utils.spring.SpringUtils; import com.ruoyi.framework.config.properties.EncryptorProperties; +import com.ruoyi.framework.manager.EncryptorManager; +import lombok.AllArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.parameter.ParameterHandler; import org.apache.ibatis.plugin.Interceptor; @@ -24,7 +28,7 @@ import java.util.Set; * 入参加密拦截器 * * @author 老马 - * @date 2023-01-10 16:42 + * @version 4.6.0 */ @Slf4j @Intercepts({@Signature( @@ -32,10 +36,11 @@ import java.util.Set; method = "setParameters", args = {PreparedStatement.class}) }) +@AllArgsConstructor public class MybatisEncryptInterceptor implements Interceptor { - private final EncryptorManager encryptorManager = SpringUtils.getBean(EncryptorManager.class); - private final EncryptorProperties defaultProperties = SpringUtils.getBean(EncryptorProperties.class); + private final EncryptorManager encryptorManager; + private final EncryptorProperties defaultProperties; @Override public Object intercept(Invocation invocation) throws Throwable { @@ -60,6 +65,7 @@ public class MybatisEncryptInterceptor implements Interceptor { * * @param sourceObject 待加密对象 */ + @SuppressWarnings("unchecked cast") private void encryptHandler(Object sourceObject) { if (sourceObject instanceof Map) { ((Map) sourceObject).values().forEach(this::encryptHandler); @@ -68,13 +74,13 @@ public class MybatisEncryptInterceptor implements Interceptor { if (sourceObject instanceof List) { // 判断第一个元素是否含有注解。如果没有直接返回,提高效率 Object firstItem = ((List) sourceObject).get(0); - if (CollectionUtil.isEmpty(EncryptedFieldsCache.get(firstItem.getClass()))) { + if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) { return; } ((List) sourceObject).forEach(this::encryptHandler); return; } - Set fields = EncryptedFieldsCache.get(sourceObject.getClass()); + Set fields = encryptorManager.getFieldCache(sourceObject.getClass()); try { for (Field field : fields) { field.set(sourceObject, this.encryptField(String.valueOf(field.get(sourceObject)), field)); @@ -93,15 +99,13 @@ public class MybatisEncryptInterceptor implements Interceptor { */ private String encryptField(String value, Field field) { EncryptField encryptField = field.getAnnotation(EncryptField.class); - EncryptorProperties properties = new EncryptorProperties(); - properties.setEnabled(true); - properties.setAlgorithm(encryptField.algorithm()); - properties.setEncode(encryptField.encode()); - properties.setPassword(StringUtils.isEmpty(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); - properties.setPrivateKey(StringUtils.isEmpty(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); - properties.setPublicKey(StringUtils.isEmpty(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); - this.encryptorManager.registAndGetEncryptor(properties); - return this.encryptorManager.encrypt(value, properties); + EncryptContext encryptContext = new EncryptContext(); + encryptContext.setAlgorithm(encryptField.algorithm() == AlgorithmType.DEFAULT ? defaultProperties.getAlgorithm() : encryptField.algorithm()); + encryptContext.setEncode(encryptField.encode() == EncodeType.DEFAULT ? defaultProperties.getEncode() : encryptField.encode()); + encryptContext.setPassword(StringUtils.isBlank(encryptField.password()) ? defaultProperties.getPassword() : encryptField.password()); + encryptContext.setPrivateKey(StringUtils.isBlank(encryptField.privateKey()) ? defaultProperties.getPrivateKey() : encryptField.privateKey()); + encryptContext.setPublicKey(StringUtils.isBlank(encryptField.publicKey()) ? defaultProperties.getPublicKey() : encryptField.publicKey()); + return this.encryptorManager.encrypt(value, encryptContext); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/EncryptorManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/EncryptorManager.java new file mode 100644 index 000000000..94515aab4 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/EncryptorManager.java @@ -0,0 +1,96 @@ +package com.ruoyi.framework.manager; + +import cn.hutool.core.util.ReflectUtil; +import com.ruoyi.common.annotation.EncryptField; +import com.ruoyi.common.encrypt.EncryptContext; +import com.ruoyi.common.encrypt.IEncryptor; +import lombok.extern.slf4j.Slf4j; + +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +/** + * 加密管理类 + * + * @author 老马 + * @version 4.6.0 + */ +@Slf4j +public class EncryptorManager { + + /** + * 缓存加密器 + */ + Map encryptorMap = new ConcurrentHashMap<>(); + + /** + * 类加密字段缓存 + */ + Map, Set> fieldCache = new ConcurrentHashMap<>(); + + /** + * 获取类加密字段缓存 + */ + public Set getFieldCache(Class sourceClazz) { + return fieldCache.computeIfAbsent(sourceClazz, clazz -> { + Field[] declaredFields = clazz.getDeclaredFields(); + Set fieldSet = Arrays.stream(declaredFields).filter(field -> + field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class) + .collect(Collectors.toSet()); + for (Field field : fieldSet) { + field.setAccessible(true); + } + return fieldSet; + }); + } + + /** + * 注册加密执行者到缓存 + * + * @param encryptContext 加密执行者需要的相关配置参数 + */ + public IEncryptor registAndGetEncryptor(EncryptContext encryptContext) { + if (encryptorMap.containsKey(encryptContext)) { + return encryptorMap.get(encryptContext); + } + IEncryptor encryptor = ReflectUtil.newInstance(encryptContext.getAlgorithm().getClazz(), encryptContext); + encryptorMap.put(encryptContext, encryptor); + return encryptor; + } + + /** + * 移除缓存中的加密执行者 + * + * @param encryptContext 加密执行者需要的相关配置参数 + */ + public void removeEncryptor(EncryptContext encryptContext) { + this.encryptorMap.remove(encryptContext); + } + + /** + * 根据配置进行加密。会进行本地缓存对应的算法和对应的秘钥信息。 + * + * @param value 待加密的值 + * @param encryptContext 加密相关的配置信息 + */ + public String encrypt(String value, EncryptContext encryptContext) { + IEncryptor encryptor = this.registAndGetEncryptor(encryptContext); + return encryptor.encrypt(value, encryptContext.getEncode()); + } + + /** + * 根据配置进行解密 + * + * @param value 待解密的值 + * @param encryptContext 加密相关的配置信息 + */ + public String decrypt(String value, EncryptContext encryptContext) { + IEncryptor encryptor = this.registAndGetEncryptor(encryptContext); + return encryptor.decrypt(value); + } + +}