From 8aacbca214848b0ee3b5c169c7aece88a2dc3125 Mon Sep 17 00:00:00 2001 From: mayuanfei Date: Sun, 8 Jan 2023 12:37:10 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=A9=E5=B1=95MP=E7=9A=84TypeHandler?= =?UTF-8?q?=EF=BC=8C=E4=BD=BFdao=E5=B1=82=E5=AE=9E=E7=8E=B0=E5=AF=B9?= =?UTF-8?q?=E8=A1=A8=E5=AD=97=E6=AE=B5=E7=9A=84=E5=8A=A0=E8=A7=A3=E5=AF=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 8 ++ .../src/main/resources/application.yml | 24 ++++ ruoyi-common/pom.xml | 6 + .../common/encrypt/EncryptTypeHandler.java | 44 ++++++ .../com/ruoyi/common/encrypt/IEncryptor.java | 41 ++++++ .../common/encrypt/IEncryptorManager.java | 25 ++++ .../com/ruoyi/common/enums/AlgorithmType.java | 35 +++++ .../TestEncryptFieldController.java | 125 ++++++++++++++++++ .../java/com/ruoyi/demo/domain/TestDemo.java | 5 +- .../properties/EncryptFieldProperties.java | 46 +++++++ .../framework/encrypt/EncryptorManager.java | 69 ++++++++++ .../encrypt/encryptor/AesEncryptor.java | 73 ++++++++++ .../encrypt/encryptor/Base64Encryptor.java | 51 +++++++ .../encrypt/encryptor/RsaEncryptor.java | 64 +++++++++ .../encrypt/encryptor/Sm2Encryptor.java | 67 ++++++++++ .../encrypt/encryptor/Sm4Encryptor.java | 64 +++++++++ 16 files changed, 746 insertions(+), 1 deletion(-) create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptTypeHandler.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptorManager.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java create mode 100644 ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptFieldController.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptFieldProperties.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptorManager.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/AesEncryptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Base64Encryptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/RsaEncryptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm2Encryptor.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm4Encryptor.java diff --git a/pom.xml b/pom.xml index 30d5132c8..49f68734a 100644 --- a/pom.xml +++ b/pom.xml @@ -36,6 +36,7 @@ 2.14.2 2.3.1 1.18.24 + 1.72 1.33 @@ -252,6 +253,13 @@ ${snakeyaml.version} + + + org.bouncycastle + bcprov-jdk15to18 + ${bouncycastle.version} + + com.ruoyi diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 77c68e496..3c6246a83 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -183,6 +183,30 @@ mybatis-plus: updateStrategy: NOT_NULL # 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件 where-strategy: NOT_NULL + # 扫描自定义TypeHandler + type-handlers-package: com.ruoyi.common.encrypt + encrypt-field: + # 字段加密算法,可自定义算法。目前支持:base64、aes、rsa、sm2、sm4。 + # 其中base64不需要公钥私钥;ras、sm2需要公私钥信息; + # aes采用AES/CBC/PKCS5Padding,需要secretKey和ivKey; + # sm4采用SM4/ECB/PKCS5Padding,需要secretKey + # encodeType可以指定最终保存的编码格式。可以是hex或base64格式。默认base64 + algorithm: base64 +# algorithm: 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== +# encodeType: base64 +# algorithm: sm2 +# publicKey: MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAESU5V56NTde1KYcp63wHEXxUyh2kwEVgVNhlQiqUQMbJJWyIDny7CW2lt71XGmm8sjmSkbGZYMcrM27H2wzp0Gw== +# privateKey: MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgM6U/o1oR8swRomlNffyqE2tglhuUcWtPEFYrCsvGUa2gCgYIKoEcz1UBgi2hRANCAARJTlXno1N17UphynrfAcRfFTKHaTARWBU2GVCKpRAxsklbIgOfLsJbaW3vVcaabyyOZKRsZlgxyszbsfbDOnQb +# encodeType: hex +# algorithm: aes +# secretKey: "A84DC2F738843E1A4170F053F5025F9A74164FFC158CB245570728CF00731803" +# ivKey: "00000000000000000000000000000000" +# encodeType: hex +# algorithm: sm4 +# secretKey: 6fyk4jdi5yrlrdcv +# encodeType: base64 # Swagger配置 swagger: diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index f88534367..232b33a3e 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -148,6 +148,12 @@ lock4j-redisson-spring-boot-starter + + + org.bouncycastle + bcprov-jdk15to18 + + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptTypeHandler.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptTypeHandler.java new file mode 100644 index 000000000..3d8d7f0d5 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/EncryptTypeHandler.java @@ -0,0 +1,44 @@ +package com.ruoyi.common.encrypt; + +import com.ruoyi.common.utils.spring.SpringUtils; +import org.apache.ibatis.type.JdbcType; +import org.apache.ibatis.type.TypeHandler; +import java.sql.CallableStatement; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; + +/** + * 加解密字段处理 + * + * @author 老马 + * @date 2023-01-06 10:46 + */ +public class EncryptTypeHandler implements TypeHandler { + + /** + * 加解密管理者 + */ + private final IEncryptorManager encryptorManager = SpringUtils.getBean(IEncryptorManager.class); + + @Override + public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException { + ps.setString(i, encryptorManager.encrypt(parameter)); + } + + + @Override + public String getResult(ResultSet rs, String columnName) throws SQLException { + return encryptorManager.decrypt(rs.getString(columnName)); + } + + @Override + public String getResult(ResultSet rs, int columnIndex) throws SQLException { + return encryptorManager.decrypt(rs.getString(columnIndex)); + } + + @Override + public String getResult(CallableStatement cs, int columnIndex) throws SQLException { + return encryptorManager.decrypt(cs.getString(columnIndex)); + } +} 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 new file mode 100644 index 000000000..b9ffa77bd --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptor.java @@ -0,0 +1,41 @@ +package com.ruoyi.common.encrypt; + +/** + * 加解密执行者 + * + * @author 老马 + * @date 2023-01-06 09:20 + */ +public interface IEncryptor { + /** + * 编码类型-16进制 + */ + String ENCODETYPE_HEX = "hex"; + + /** + * 是否为本加解密处理的算法名称 + * + * @param algorithm 算法名称 + * @return 是否本类能处理的算法 + */ + Boolean isMyAlgorithm(String algorithm); + + /** + * 加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + * @throws Exception 抛出异常 + */ + String encrypt(String value) throws Exception; + + /** + * 解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + * @throws Exception 抛出异常 + */ + String decrypt(String value) throws Exception; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptorManager.java b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptorManager.java new file mode 100644 index 000000000..c720ceb60 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/encrypt/IEncryptorManager.java @@ -0,0 +1,25 @@ +package com.ruoyi.common.encrypt; + +/** + * 加解密管理者接口 + * + * @author 老马 + * @date 2023-01-08 12:01 + */ +public interface IEncryptorManager { + /** + * 调用具体的执行者进行加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + */ + String encrypt(String value); + + /** + * 调用具体的执行者进行解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + */ + String decrypt(String 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 new file mode 100644 index 000000000..8aaf7f465 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/AlgorithmType.java @@ -0,0 +1,35 @@ +package com.ruoyi.common.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 算法名称 + * @author 老马 + */ +@Getter +@AllArgsConstructor +public enum AlgorithmType { + /** + * base64 + */ + BASE64("base64"), + /** + * aes + */ + AES("aes"), + /** + * rsa + */ + RSA("rsa"), + /** + * sm2 + */ + SM2("sm2"), + /** + * sm4 + */ + SM4("sm4"); + + private final String algorithm; +} diff --git a/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptFieldController.java b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptFieldController.java new file mode 100644 index 000000000..58d59bc93 --- /dev/null +++ b/ruoyi-demo/src/main/java/com/ruoyi/demo/controller/TestEncryptFieldController.java @@ -0,0 +1,125 @@ +package com.ruoyi.demo.controller; + +import cn.dev33.satoken.annotation.SaIgnore; +import com.ruoyi.common.core.domain.R; +import com.ruoyi.demo.domain.TestDemo; +import com.ruoyi.demo.mapper.TestDemoMapper; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.annotation.Resource; + +/** + * 测试数据库字段加解密 + * + * @author 老马 + * @date 2023-01-06 14:48 + */ +@SaIgnore +@RestController +@RequestMapping("/demo/encrypt") +public class TestEncryptFieldController { + + @Resource + private TestDemoMapper demoMapper; + + /** + * 配置内容 + * encrypt-field: + algorithm: base64 + */ + @GetMapping("/base64") + public R base64() { + //插入 + TestDemo testDemo = new TestDemo(); + testDemo.setTestKey("testkey"); + testDemo.setValue("testvalue"); + demoMapper.insert(testDemo); + //查询 + TestDemo testDemo1 = this.demoMapper.selectById(testDemo.getId()); + return R.ok(testDemo1); + } + + /** + * 配置内容 + * encrypt-field: + algorithm: aes + encodeKey: A84DC2F738843E1A4170F053F5025F9A74164FFC158CB245570728CF00731803 + ivKey: 00000000000000000000000000000000 + encodeType: hex + */ + @GetMapping("/aes") + public R aes() { + //插入 + TestDemo testDemo = new TestDemo(); + testDemo.setTestKey("testkey"); + testDemo.setValue("testvalue"); + demoMapper.insert(testDemo); + //查询 + TestDemo testDemo1 = this.demoMapper.selectById(testDemo.getId()); + return R.ok(testDemo1); + } + + + /** + * 配置内容 + * encrypt-field: + algorithm: 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== + encodeType: base64 + */ + @GetMapping("/rsa") + public R rsa() { + //插入 + TestDemo testDemo = new TestDemo(); + testDemo.setTestKey("testkey"); + testDemo.setValue("testvalue"); + demoMapper.insert(testDemo); + //查询 + TestDemo testDemo1 = this.demoMapper.selectById(testDemo.getId()); + return R.ok(testDemo1); + } + + + /** + * 配置内容 + * encrypt-field: + algorithm: sm2 + publicKey: MFkwEwYHKoZIzj0CAQYIKoEcz1UBgi0DQgAESU5V56NTde1KYcp63wHEXxUyh2kwEVgVNhlQiqUQMbJJWyIDny7CW2lt71XGmm8sjmSkbGZYMcrM27H2wzp0Gw== + privateKey: MIGTAgEAMBMGByqGSM49AgEGCCqBHM9VAYItBHkwdwIBAQQgM6U/o1oR8swRomlNffyqE2tglhuUcWtPEFYrCsvGUa2gCgYIKoEcz1UBgi2hRANCAARJTlXno1N17UphynrfAcRfFTKHaTARWBU2GVCKpRAxsklbIgOfLsJbaW3vVcaabyyOZKRsZlgxyszbsfbDOnQb + encodeType: base64 + */ + @GetMapping("/sm2") + public R sm2() { + //插入 + TestDemo testDemo = new TestDemo(); + testDemo.setTestKey("testkey"); + testDemo.setValue("testvalue"); + demoMapper.insert(testDemo); + //查询 + TestDemo testDemo1 = this.demoMapper.selectById(testDemo.getId()); + return R.ok(testDemo1); + } + + /** + * 配置内容 + * encrypt-field: + algorithm: sm4 + encodeKey: 8qwo86o2psmakww2qe2mv0ivk5gru2op + encodeType: base64 + */ + @GetMapping("/sm4") + public R sm4() { + //插入 + TestDemo testDemo = new TestDemo(); + testDemo.setTestKey("testkey"); + testDemo.setValue("testvalue"); + demoMapper.insert(testDemo); + //查询 + TestDemo testDemo1 = this.demoMapper.selectById(testDemo.getId()); + return R.ok(testDemo1); + } + +} 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 dc19ce2c7..affdc7ff7 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 @@ -2,6 +2,7 @@ package com.ruoyi.demo.domain; import com.baomidou.mybatisplus.annotation.*; import com.ruoyi.common.core.domain.BaseEntity; +import com.ruoyi.common.encrypt.EncryptTypeHandler; import lombok.Data; import lombok.EqualsAndHashCode; @@ -13,7 +14,7 @@ import lombok.EqualsAndHashCode; */ @Data @EqualsAndHashCode(callSuper = true) -@TableName("test_demo") +@TableName(value = "test_demo", autoResultMap = true) public class TestDemo extends BaseEntity { private static final long serialVersionUID = 1L; @@ -44,11 +45,13 @@ public class TestDemo extends BaseEntity { /** * key键 */ + @TableField(typeHandler = EncryptTypeHandler.class) private String testKey; /** * 值 */ + @TableField(typeHandler = EncryptTypeHandler.class) private String value; /** diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptFieldProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptFieldProperties.java new file mode 100644 index 000000000..ed9fe8141 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/EncryptFieldProperties.java @@ -0,0 +1,46 @@ +package com.ruoyi.framework.config.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +/** + * 加密字段属性配置 + * + * @author 老马 + * @date 2023-01-06 08:57 + */ +@Data +@Component +@ConfigurationProperties(prefix = "mybatis-plus.encrypt-field") +public class EncryptFieldProperties { + /** + * 算法名称 + */ + private String algorithm; + + /** + * 字符串的编码方式 + */ + private String encodeType; + + /** + * 非对称加密算法的公钥 + */ + private String publicKey; + + /** + * 非对称加密算法的私钥 + */ + private String privateKey; + + /** + * AES和SM4 的 秘钥 + */ + private String secretKey; + + /** + * AES 的 ivKey + */ + private String ivKey; +} 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 new file mode 100644 index 000000000..dfa33cc78 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/EncryptorManager.java @@ -0,0 +1,69 @@ +package com.ruoyi.framework.encrypt; + +import com.ruoyi.common.encrypt.IEncryptor; +import com.ruoyi.common.encrypt.IEncryptorManager; +import com.ruoyi.framework.config.properties.EncryptFieldProperties; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import java.util.List; + +/** + * 加解密管理者 + * + * @author 老马 + * @date 2023-01-06 09:19 + */ +@Slf4j +@Component +public class EncryptorManager implements IEncryptorManager { + @Resource + private EncryptFieldProperties properties; + @Resource + private List encryptors; + + /** + * 加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + */ + @Override + public String encrypt(String value) { + try { + for(IEncryptor encryptor : encryptors) { + if(encryptor.isMyAlgorithm(properties.getAlgorithm())) { + return encryptor.encrypt(value); + } + } + //没有加解密执行者或者算法名找不到时,还是返回原字符串 + return value; + }catch (Exception e) { + log.error("字段加密异常,原样返回。异常信息:【{}】", e.getMessage()); + return value; + } + } + + /** + * 解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + */ + @Override + public String decrypt(String value) { + try { + for(IEncryptor encryptor : encryptors) { + if(encryptor.isMyAlgorithm(properties.getAlgorithm())) { + return encryptor.decrypt(value); + } + } + //没有加解密执行者或者算法名找不到时,还是返回原字符串 + return value; + }catch(Exception e) { + log.error("字段解密异常,原样返回。异常信息:【{}】", e.getMessage()); + return value; + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/AesEncryptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/AesEncryptor.java new file mode 100644 index 000000000..18ea58254 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/AesEncryptor.java @@ -0,0 +1,73 @@ +package com.ruoyi.framework.encrypt.encryptor; + +import cn.hutool.core.util.HexUtil; +import cn.hutool.crypto.Mode; +import cn.hutool.crypto.Padding; +import cn.hutool.crypto.symmetric.AES; +import com.ruoyi.common.encrypt.IEncryptor; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.config.properties.EncryptFieldProperties; +import org.springframework.stereotype.Component; +import javax.annotation.Resource; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.SecretKeySpec; + +/** + * AES算法实现 + * + * @author 老马 + * @date 2023-01-06 11:39 + */ +@Component +public class AesEncryptor implements IEncryptor { + + @Resource + private EncryptFieldProperties properties; + + /** + * 是否为本加解密处理的算法名称 + * + * @param algorithm 算法名称 + * @return 是否本类能处理的算法 + */ + @Override + public Boolean isMyAlgorithm(String algorithm) { + return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.AES.getAlgorithm()); + } + + /** + * AES加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String encrypt(String value) throws Exception { + + AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, + new SecretKeySpec(HexUtil.decodeHex(properties.getSecretKey()), StringUtils.toRootUpperCase(properties.getAlgorithm())), + new IvParameterSpec(HexUtil.decodeHex(properties.getIvKey()))); + if(StringUtils.endsWithIgnoreCase(properties.getEncodeType(), IEncryptor.ENCODETYPE_HEX)) { + return aes.encryptHex(value); + }else { + return aes.encryptBase64(value); + } + } + + /** + * AES解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String decrypt(String value) throws Exception { + AES aes = new AES(Mode.CBC, Padding.PKCS5Padding, + new SecretKeySpec(HexUtil.decodeHex(properties.getSecretKey()), properties.getAlgorithm()), + new IvParameterSpec(HexUtil.decodeHex(properties.getIvKey()))); + return aes.decryptStr(value); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Base64Encryptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Base64Encryptor.java new file mode 100644 index 000000000..818746ef3 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Base64Encryptor.java @@ -0,0 +1,51 @@ +package com.ruoyi.framework.encrypt.encryptor; + +import cn.hutool.core.codec.Base64; +import com.ruoyi.common.encrypt.IEncryptor; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.stereotype.Component; + +/** + * Base64算法实现。不建议在生产环境使用 + * + * @author 老马 + * @date 2023-01-06 10:00 + */ +@Component +public class Base64Encryptor implements IEncryptor { + /** + * 是否为本加解密处理的算法名称 + * + * @param algorithm 算法名称 + * @return 是否本类能处理的算法 + */ + @Override + public Boolean isMyAlgorithm(String algorithm) { + return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.BASE64.getAlgorithm()); + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String encrypt(String value) throws Exception { + return Base64.encode(value); + } + + /** + * 解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String decrypt(String value) throws Exception { + return Base64.decodeStr(value); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/RsaEncryptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/RsaEncryptor.java new file mode 100644 index 000000000..de91329e0 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/RsaEncryptor.java @@ -0,0 +1,64 @@ +package com.ruoyi.framework.encrypt.encryptor; + +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.RSA; +import com.ruoyi.common.encrypt.IEncryptor; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.config.properties.EncryptFieldProperties; +import org.springframework.stereotype.Component; +import javax.annotation.Resource; + +/** + * RSA算法实现 + * + * @author 老马 + * @date 2023-01-06 09:37 + */ +@Component +public class RsaEncryptor implements IEncryptor { + + @Resource + private EncryptFieldProperties properties; + + /** + * 是否为本加解密处理的算法名称 + * + * @param algorithm 算法名称 + * @return 是否本类能处理的算法 + */ + @Override + public Boolean isMyAlgorithm(String algorithm) { + return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.RSA.getAlgorithm()); + } + + /** + * 公钥加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String encrypt(String value) throws Exception { + RSA rsa = new RSA(properties.getPrivateKey(), properties.getPublicKey()); + if(StringUtils.endsWithIgnoreCase(properties.getEncodeType(), IEncryptor.ENCODETYPE_HEX)) { + return rsa.encryptHex(value, KeyType.PublicKey); + }else { + return rsa.encryptBase64(value, KeyType.PublicKey); + } + } + + /** + * 私钥解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String decrypt(String value) throws Exception { + RSA rsa = new RSA(properties.getPrivateKey(), properties.getPublicKey()); + return rsa.decryptStr(value, KeyType.PrivateKey); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm2Encryptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm2Encryptor.java new file mode 100644 index 000000000..1180e269e --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm2Encryptor.java @@ -0,0 +1,67 @@ +package com.ruoyi.framework.encrypt.encryptor; + +import cn.hutool.crypto.SmUtil; +import cn.hutool.crypto.asymmetric.KeyType; +import cn.hutool.crypto.asymmetric.SM2; +import com.ruoyi.common.encrypt.IEncryptor; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.config.properties.EncryptFieldProperties; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * sm2算法实现 + * + * @author 老马 + * @date 2023-01-06 17:13 + */ +@Component +public class Sm2Encryptor implements IEncryptor { + + @Resource + private EncryptFieldProperties properties; + + + /** + * 是否为本加解密处理的算法名称 + * + * @param algorithm 算法名称 + * @return 是否本类能处理的算法 + */ + @Override + public Boolean isMyAlgorithm(String algorithm) { + return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.SM2.getAlgorithm()); + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String encrypt(String value) throws Exception { + SM2 sm2 = SmUtil.sm2(properties.getPrivateKey(), properties.getPublicKey()); + if(StringUtils.endsWithIgnoreCase(properties.getEncodeType(), IEncryptor.ENCODETYPE_HEX)) { + return sm2.encryptHex(value, KeyType.PublicKey); + }else { + return sm2.encryptBase64(value, KeyType.PublicKey); + } + } + + /** + * 解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String decrypt(String value) throws Exception { + SM2 sm2 = SmUtil.sm2(properties.getPrivateKey(), properties.getPublicKey()); + return sm2.decryptStr(value, KeyType.PrivateKey); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm4Encryptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm4Encryptor.java new file mode 100644 index 000000000..5506f13fb --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/encrypt/encryptor/Sm4Encryptor.java @@ -0,0 +1,64 @@ +package com.ruoyi.framework.encrypt.encryptor; + +import cn.hutool.crypto.symmetric.SymmetricCrypto; +import com.ruoyi.common.encrypt.IEncryptor; +import com.ruoyi.common.enums.AlgorithmType; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.framework.config.properties.EncryptFieldProperties; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * sm4算法实现 + * + * @author 老马 + * @date 2023-01-06 17:40 + */ +@Component +public class Sm4Encryptor implements IEncryptor { + + @Resource + private EncryptFieldProperties properties; + + /** + * 是否为本加解密处理的算法名称 + * + * @param algorithm 算法名称 + * @return 是否本类能处理的算法 + */ + @Override + public Boolean isMyAlgorithm(String algorithm) { + return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.SM4.getAlgorithm()); + } + + /** + * 加密 + * + * @param value 待加密字符串 + * @return 加密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String encrypt(String value) throws Exception{ + SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", properties.getSecretKey().getBytes()); + if(StringUtils.endsWithIgnoreCase(properties.getEncodeType(), IEncryptor.ENCODETYPE_HEX)) { + return sm4.encryptHex(value); + }else { + return sm4.encryptBase64(value); + } + } + + /** + * 解密 + * + * @param value 待解密字符串 + * @return 解密后的字符串 + * @throws Exception 抛出异常 + */ + @Override + public String decrypt(String value) throws Exception{ + SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", properties.getSecretKey().getBytes()); + return sm4.decryptStr(value); + } +}