mirror of
https://gitee.com/dromara/RuoYi-Vue-Plus.git
synced 2026-09-21 02:25:56 +08:00
扩展MP的TypeHandler,使dao层实现对表字段的加解密功能
This commit is contained in:
parent
1496220a74
commit
ecb6fcc2c5
8
pom.xml
8
pom.xml
@ -36,6 +36,7 @@
|
|||||||
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
|
<alibaba-ttl.version>2.14.2</alibaba-ttl.version>
|
||||||
<xxl-job.version>2.3.1</xxl-job.version>
|
<xxl-job.version>2.3.1</xxl-job.version>
|
||||||
<lombok.version>1.18.24</lombok.version>
|
<lombok.version>1.18.24</lombok.version>
|
||||||
|
<bouncycastle.version>1.72</bouncycastle.version>
|
||||||
|
|
||||||
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
|
<!-- 统一 guava 版本 解决隐式漏洞问题 -->
|
||||||
<guava.version>31.1-jre</guava.version>
|
<guava.version>31.1-jre</guava.version>
|
||||||
@ -235,6 +236,13 @@
|
|||||||
<version>${snakeyaml.version}</version>
|
<version>${snakeyaml.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 加密包引入 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15to18</artifactId>
|
||||||
|
<version>${bouncycastle.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 定时任务 -->
|
<!-- 定时任务 -->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
|
|||||||
@ -176,7 +176,30 @@ mybatis-plus:
|
|||||||
updateStrategy: NOT_NULL
|
updateStrategy: NOT_NULL
|
||||||
# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
|
# 字段验证策略之 select,在 select 的时候的字段验证策略既 wrapper 根据内部 entity 生成的 where 条件
|
||||||
where-strategy: NOT_NULL
|
where-strategy: NOT_NULL
|
||||||
|
# 扫描自定义TypeHandler
|
||||||
|
type-handlers-package: com.ruoyi.framework.handler
|
||||||
|
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配置
|
||||||
swagger:
|
swagger:
|
||||||
# 是否开启swagger
|
# 是否开启swagger
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
@ -23,6 +23,11 @@
|
|||||||
<artifactId>ruoyi-common</artifactId>
|
<artifactId>ruoyi-common</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-framework</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
<artifactId>ruoyi-sms</artifactId>
|
<artifactId>ruoyi-sms</artifactId>
|
||||||
|
|||||||
@ -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<TestDemo> 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<TestDemo> 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<TestDemo> 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<TestDemo> 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<TestDemo> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@ package com.ruoyi.demo.domain;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.*;
|
import com.baomidou.mybatisplus.annotation.*;
|
||||||
import com.ruoyi.common.core.domain.BaseEntity;
|
import com.ruoyi.common.core.domain.BaseEntity;
|
||||||
|
import com.ruoyi.framework.handler.EncryptTypeHandler;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
@ -13,7 +14,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@EqualsAndHashCode(callSuper = true)
|
@EqualsAndHashCode(callSuper = true)
|
||||||
@TableName("test_demo")
|
@TableName(value="test_demo", autoResultMap=true)
|
||||||
public class TestDemo extends BaseEntity {
|
public class TestDemo extends BaseEntity {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1L;
|
private static final long serialVersionUID = 1L;
|
||||||
@ -44,11 +45,13 @@ public class TestDemo extends BaseEntity {
|
|||||||
/**
|
/**
|
||||||
* key键
|
* key键
|
||||||
*/
|
*/
|
||||||
|
@TableField(typeHandler = EncryptTypeHandler.class)
|
||||||
private String testKey;
|
private String testKey;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 值
|
* 值
|
||||||
*/
|
*/
|
||||||
|
@TableField(typeHandler = EncryptTypeHandler.class)
|
||||||
private String value;
|
private String value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -61,6 +61,11 @@
|
|||||||
<artifactId>transmittable-thread-local</artifactId>
|
<artifactId>transmittable-thread-local</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15to18</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<!-- 系统模块-->
|
<!-- 系统模块-->
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.ruoyi</groupId>
|
<groupId>com.ruoyi</groupId>
|
||||||
|
|||||||
@ -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;
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.ruoyi.framework.handler;
|
||||||
|
|
||||||
|
import com.ruoyi.common.utils.spring.SpringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
import com.ruoyi.framework.manager.EncryptorManager;
|
||||||
|
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<String> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加解密管理者
|
||||||
|
*/
|
||||||
|
private final EncryptorManager encryptorManager = SpringUtils.getBean(EncryptorManager.class);
|
||||||
|
private final EncryptFieldProperties properties = SpringUtils.getBean(EncryptFieldProperties.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setParameter(PreparedStatement ps, int i, String parameter, JdbcType jdbcType) throws SQLException {
|
||||||
|
ps.setString(i, encryptorManager.encrypt(parameter, properties));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResult(ResultSet rs, String columnName) throws SQLException {
|
||||||
|
return encryptorManager.decrypt(rs.getString(columnName), properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||||
|
return encryptorManager.decrypt(rs.getString(columnIndex), properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||||
|
return encryptorManager.decrypt(cs.getString(columnIndex), properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,66 @@
|
|||||||
|
package com.ruoyi.framework.manager;
|
||||||
|
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
import com.ruoyi.framework.manager.encryptor.IEncryptor;
|
||||||
|
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 {
|
||||||
|
@Resource
|
||||||
|
private List<IEncryptor> encryptors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 加密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
public String encrypt(String value, EncryptFieldProperties properties) {
|
||||||
|
try {
|
||||||
|
for(IEncryptor encryptor : encryptors) {
|
||||||
|
if(encryptor.isMyAlgorithm(properties.getAlgorithm())) {
|
||||||
|
return encryptor.encrypt(value, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//没有加解密执行者或者算法名找不到时,还是返回原字符串
|
||||||
|
return value;
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.error("字段加密异常,原样返回。异常信息:【{}】", e.getMessage());
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
* @param value 待解密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 解密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
public String decrypt(String value, EncryptFieldProperties properties) {
|
||||||
|
try {
|
||||||
|
for(IEncryptor encryptor : encryptors) {
|
||||||
|
if(encryptor.isMyAlgorithm(properties.getAlgorithm())) {
|
||||||
|
return encryptor.decrypt(value, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//没有加解密执行者或者算法名找不到时,还是返回原字符串
|
||||||
|
return value;
|
||||||
|
}catch(Exception e) {
|
||||||
|
log.error("字段解密异常,原样返回。异常信息:【{}】", e.getMessage());
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,72 @@
|
|||||||
|
package com.ruoyi.framework.manager.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.enums.AlgorithmType;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
import com.ruoyi.framework.manager.encryptor.IEncryptor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES算法实现
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @date 2023-01-06 11:39
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AesEncryptor implements IEncryptor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为本加解密处理的算法名称
|
||||||
|
*
|
||||||
|
* @param algorithm 算法名称
|
||||||
|
* @return 是否本类能处理的算法
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean isMyAlgorithm(String algorithm) {
|
||||||
|
return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.AES.getAlgorithm());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES加密
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 加密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String encrypt(String value, EncryptFieldProperties properties) 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 待解密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 解密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String decrypt(String value, EncryptFieldProperties properties) 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,54 @@
|
|||||||
|
package com.ruoyi.framework.manager.encryptor;
|
||||||
|
|
||||||
|
import cn.hutool.core.codec.Base64;
|
||||||
|
import com.ruoyi.common.enums.AlgorithmType;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
import com.ruoyi.framework.manager.encryptor.IEncryptor;
|
||||||
|
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 待加密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 加密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String encrypt(String value, EncryptFieldProperties properties) throws Exception {
|
||||||
|
return Base64.encode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
*
|
||||||
|
* @param value 待解密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 解密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String decrypt(String value, EncryptFieldProperties properties) throws Exception {
|
||||||
|
return Base64.decodeStr(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
package com.ruoyi.framework.manager.encryptor;
|
||||||
|
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加解密执行者
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @date 2023-01-06 09:20
|
||||||
|
*/
|
||||||
|
public interface IEncryptor {
|
||||||
|
/**
|
||||||
|
* 编码类型-16进制
|
||||||
|
*/
|
||||||
|
String ENCODETYPE_HEX = "hex";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否为本加解密处理的算法名称
|
||||||
|
* @param algorithm 算法名称
|
||||||
|
* @return 是否本类能处理的算法
|
||||||
|
*/
|
||||||
|
Boolean isMyAlgorithm(String algorithm);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 加密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
String encrypt(String value, EncryptFieldProperties properties) throws Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
* @param value 待解密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 解密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
String decrypt(String value, EncryptFieldProperties properties) throws Exception;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.ruoyi.framework.manager.encryptor;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.asymmetric.KeyType;
|
||||||
|
import cn.hutool.crypto.asymmetric.RSA;
|
||||||
|
import com.ruoyi.common.enums.AlgorithmType;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
import com.ruoyi.framework.manager.encryptor.IEncryptor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RSA算法实现
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @date 2023-01-06 09:37
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RsaEncryptor implements IEncryptor {
|
||||||
|
/**
|
||||||
|
* 是否为本加解密处理的算法名称
|
||||||
|
*
|
||||||
|
* @param algorithm 算法名称
|
||||||
|
* @return 是否本类能处理的算法
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean isMyAlgorithm(String algorithm) {
|
||||||
|
return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.RSA.getAlgorithm());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥加密
|
||||||
|
* 需要从properties读取公私钥信息
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 加密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String encrypt(String value, EncryptFieldProperties properties) 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 待解密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 解密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String decrypt(String value, EncryptFieldProperties properties) throws Exception {
|
||||||
|
RSA rsa = new RSA(properties.getPrivateKey(), properties.getPublicKey());
|
||||||
|
return rsa.decryptStr(value, KeyType.PrivateKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
package com.ruoyi.framework.manager.encryptor;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.SmUtil;
|
||||||
|
import cn.hutool.crypto.asymmetric.KeyType;
|
||||||
|
import cn.hutool.crypto.asymmetric.SM2;
|
||||||
|
import com.ruoyi.common.enums.AlgorithmType;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
import com.ruoyi.framework.manager.encryptor.IEncryptor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sm2算法实现
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @date 2023-01-06 17:13
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class Sm2Encryptor implements IEncryptor {
|
||||||
|
/**
|
||||||
|
* 是否为本加解密处理的算法名称
|
||||||
|
*
|
||||||
|
* @param algorithm 算法名称
|
||||||
|
* @return 是否本类能处理的算法
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean isMyAlgorithm(String algorithm) {
|
||||||
|
return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.SM2.getAlgorithm());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 加密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String encrypt(String value, EncryptFieldProperties properties) 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 待解密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 解密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String decrypt(String value, EncryptFieldProperties properties) throws Exception {
|
||||||
|
SM2 sm2 = SmUtil.sm2(properties.getPrivateKey(), properties.getPublicKey());
|
||||||
|
return sm2.decryptStr(value, KeyType.PrivateKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,60 @@
|
|||||||
|
package com.ruoyi.framework.manager.encryptor;
|
||||||
|
|
||||||
|
import cn.hutool.crypto.symmetric.SymmetricCrypto;
|
||||||
|
import com.ruoyi.common.enums.AlgorithmType;
|
||||||
|
import com.ruoyi.common.utils.StringUtils;
|
||||||
|
import com.ruoyi.framework.config.properties.EncryptFieldProperties;
|
||||||
|
import com.ruoyi.framework.manager.encryptor.IEncryptor;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sm4算法实现
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @date 2023-01-06 17:40
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class Sm4Encryptor implements IEncryptor {
|
||||||
|
/**
|
||||||
|
* 是否为本加解密处理的算法名称
|
||||||
|
*
|
||||||
|
* @param algorithm 算法名称
|
||||||
|
* @return 是否本类能处理的算法
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Boolean isMyAlgorithm(String algorithm) {
|
||||||
|
return StringUtils.equalsIgnoreCase(algorithm, AlgorithmType.SM4.getAlgorithm());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 加密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String encrypt(String value, EncryptFieldProperties properties) 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 待解密字符串
|
||||||
|
* @param properties 加解密配置信息
|
||||||
|
* @return 解密后的字符串
|
||||||
|
* @throws Exception 抛出异常
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String decrypt(String value, EncryptFieldProperties properties) throws Exception {
|
||||||
|
SymmetricCrypto sm4 = new SymmetricCrypto("SM4/ECB/PKCS5Padding", properties.getSecretKey().getBytes());
|
||||||
|
return sm4.decryptStr(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user