add 新增 数据加解密模块 ruoyi-common-encrypt
parent
e039986248
commit
0711d75c66
@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<parent>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common</artifactId>
|
||||||
|
<version>1.5.0</version>
|
||||||
|
</parent>
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<artifactId>ruoyi-common-encrypt</artifactId>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
ruoyi-common-encrypt 数据加解密模块
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.ruoyi</groupId>
|
||||||
|
<artifactId>ruoyi-common-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bouncycastle</groupId>
|
||||||
|
<artifactId>bcprov-jdk15to18</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-crypto</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.ruoyi.common.encrypt.annotation;
|
||||||
|
|
||||||
|
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.EncodeType;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段加密注解
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
*/
|
||||||
|
@Documented
|
||||||
|
@Inherited
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
public @interface EncryptField {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密算法
|
||||||
|
*/
|
||||||
|
AlgorithmType algorithm() default AlgorithmType.DEFAULT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 秘钥。AES、SM4需要
|
||||||
|
*/
|
||||||
|
String password() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥。RSA、SM2需要
|
||||||
|
*/
|
||||||
|
String publicKey() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公钥。RSA、SM2需要
|
||||||
|
*/
|
||||||
|
String privateKey() default "";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码方式。对加密算法为BASE64的不起作用
|
||||||
|
*/
|
||||||
|
EncodeType encode() default EncodeType.DEFAULT;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,39 @@
|
|||||||
|
package com.ruoyi.common.encrypt.config;
|
||||||
|
|
||||||
|
import com.ruoyi.common.encrypt.core.EncryptorManager;
|
||||||
|
import com.ruoyi.common.encrypt.interceptor.MybatisDecryptInterceptor;
|
||||||
|
import com.ruoyi.common.encrypt.interceptor.MybatisEncryptInterceptor;
|
||||||
|
import com.ruoyi.common.encrypt.properties.EncryptorProperties;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||||
|
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加解密配置
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
@AutoConfiguration
|
||||||
|
@ConditionalOnProperty(value = "mybatis-encryptor.enable", havingValue = "true")
|
||||||
|
public class EncryptorAutoConfiguration {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private EncryptorProperties properties;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public EncryptorManager encryptorManager() {
|
||||||
|
return new EncryptorManager();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MybatisEncryptInterceptor mybatisEncryptInterceptor(EncryptorManager encryptorManager) {
|
||||||
|
return new MybatisEncryptInterceptor(encryptorManager, properties);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public MybatisDecryptInterceptor mybatisDecryptInterceptor(EncryptorManager encryptorManager) {
|
||||||
|
return new MybatisDecryptInterceptor(encryptorManager, properties);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,94 @@
|
|||||||
|
package com.ruoyi.common.encrypt.core;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.ReflectUtil;
|
||||||
|
import com.ruoyi.common.encrypt.annotation.EncryptField;
|
||||||
|
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<EncryptContext, IEncryptor> encryptorMap = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 类加密字段缓存
|
||||||
|
*/
|
||||||
|
Map<Class<?>, Set<Field>> fieldCache = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取类加密字段缓存
|
||||||
|
*/
|
||||||
|
public Set<Field> getFieldCache(Class<?> sourceClazz) {
|
||||||
|
return fieldCache.computeIfAbsent(sourceClazz, clazz -> {
|
||||||
|
Field[] declaredFields = clazz.getDeclaredFields();
|
||||||
|
Set<Field> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,35 @@
|
|||||||
|
package com.ruoyi.common.encrypt.core;
|
||||||
|
|
||||||
|
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.EncodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加解者
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
public interface IEncryptor {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得当前算法
|
||||||
|
*/
|
||||||
|
AlgorithmType algorithm();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param encodeType 加密后的编码格式
|
||||||
|
* @return 加密后的字符串
|
||||||
|
*/
|
||||||
|
String encrypt(String value, EncodeType encodeType);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @return 解密后的字符串
|
||||||
|
*/
|
||||||
|
String decrypt(String value);
|
||||||
|
}
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.ruoyi.common.encrypt.core.encryptor;
|
||||||
|
|
||||||
|
import com.ruoyi.common.encrypt.core.EncryptContext;
|
||||||
|
import com.ruoyi.common.encrypt.core.IEncryptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 所有加密执行者的基类
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
public abstract class AbstractEncryptor implements IEncryptor {
|
||||||
|
|
||||||
|
public AbstractEncryptor(EncryptContext context) {
|
||||||
|
// 用户配置校验与配置注入
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.ruoyi.common.encrypt.core.encryptor;
|
||||||
|
|
||||||
|
import cn.hutool.core.codec.Base64;
|
||||||
|
import com.ruoyi.common.encrypt.core.EncryptContext;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.EncodeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base64算法实现
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
public class Base64Encryptor extends AbstractEncryptor {
|
||||||
|
|
||||||
|
public Base64Encryptor(EncryptContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得当前算法
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public AlgorithmType algorithm() {
|
||||||
|
return AlgorithmType.BASE64;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
* @param encodeType 加密后的编码格式
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String encrypt(String value, EncodeType encodeType) {
|
||||||
|
return Base64.encode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密
|
||||||
|
*
|
||||||
|
* @param value 待加密字符串
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String decrypt(String value) {
|
||||||
|
return Base64.decodeStr(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,48 @@
|
|||||||
|
package com.ruoyi.common.encrypt.enumd;
|
||||||
|
|
||||||
|
import com.ruoyi.common.encrypt.core.encryptor.*;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 算法名称
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum AlgorithmType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认走yml配置
|
||||||
|
*/
|
||||||
|
DEFAULT(null),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base64
|
||||||
|
*/
|
||||||
|
BASE64(Base64Encryptor.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* aes
|
||||||
|
*/
|
||||||
|
AES(AesEncryptor.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* rsa
|
||||||
|
*/
|
||||||
|
RSA(RsaEncryptor.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sm2
|
||||||
|
*/
|
||||||
|
SM2(Sm2Encryptor.class),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sm4
|
||||||
|
*/
|
||||||
|
SM4(Sm4Encryptor.class);
|
||||||
|
|
||||||
|
private final Class<? extends AbstractEncryptor> clazz;
|
||||||
|
}
|
||||||
@ -0,0 +1,26 @@
|
|||||||
|
package com.ruoyi.common.encrypt.enumd;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编码类型
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
public enum EncodeType {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 默认使用yml配置
|
||||||
|
*/
|
||||||
|
DEFAULT,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* base64编码
|
||||||
|
*/
|
||||||
|
BASE64,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 16进制编码
|
||||||
|
*/
|
||||||
|
HEX;
|
||||||
|
|
||||||
|
}
|
||||||
@ -0,0 +1,108 @@
|
|||||||
|
package com.ruoyi.common.encrypt.interceptor;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.encrypt.annotation.EncryptField;
|
||||||
|
import com.ruoyi.common.encrypt.core.EncryptContext;
|
||||||
|
import com.ruoyi.common.encrypt.core.EncryptorManager;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.EncodeType;
|
||||||
|
import com.ruoyi.common.encrypt.properties.EncryptorProperties;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.ibatis.executor.resultset.ResultSetHandler;
|
||||||
|
import org.apache.ibatis.plugin.*;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.Statement;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 出参解密拦截器
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Intercepts({@Signature(
|
||||||
|
type = ResultSetHandler.class,
|
||||||
|
method = "handleResultSets",
|
||||||
|
args = {Statement.class})
|
||||||
|
})
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MybatisDecryptInterceptor implements Interceptor {
|
||||||
|
|
||||||
|
private final EncryptorManager encryptorManager;
|
||||||
|
private final EncryptorProperties defaultProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object intercept(Invocation invocation) throws Throwable {
|
||||||
|
// 获取执行mysql执行结果
|
||||||
|
Object result = invocation.proceed();
|
||||||
|
if (result == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
decryptHandler(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密对象
|
||||||
|
*
|
||||||
|
* @param sourceObject 待加密对象
|
||||||
|
*/
|
||||||
|
private void decryptHandler(Object sourceObject) {
|
||||||
|
if (sourceObject instanceof Map) {
|
||||||
|
((Map<?, Object>) sourceObject).values().forEach(this::decryptHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sourceObject instanceof List) {
|
||||||
|
// 判断第一个元素是否含有注解。如果没有直接返回,提高效率
|
||||||
|
Object firstItem = ((List<?>) sourceObject).get(0);
|
||||||
|
if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
((List<?>) sourceObject).forEach(this::decryptHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Field> fields = encryptorManager.getFieldCache(sourceObject.getClass());
|
||||||
|
try {
|
||||||
|
for (Field field : fields) {
|
||||||
|
field.set(sourceObject, this.decryptField(String.valueOf(field.get(sourceObject)), field));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理解密字段时出错", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段值进行加密。通过字段的批注注册新的加密算法
|
||||||
|
*
|
||||||
|
* @param value 待加密的值
|
||||||
|
* @param field 待加密字段
|
||||||
|
* @return 加密后结果
|
||||||
|
*/
|
||||||
|
private String decryptField(String value, Field field) {
|
||||||
|
EncryptField encryptField = field.getAnnotation(EncryptField.class);
|
||||||
|
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
|
||||||
|
public Object plugin(Object target) {
|
||||||
|
return Plugin.wrap(target, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProperties(Properties properties) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,115 @@
|
|||||||
|
package com.ruoyi.common.encrypt.interceptor;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollectionUtil;
|
||||||
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
|
import com.ruoyi.common.core.utils.StringUtils;
|
||||||
|
import com.ruoyi.common.encrypt.annotation.EncryptField;
|
||||||
|
import com.ruoyi.common.encrypt.core.EncryptContext;
|
||||||
|
import com.ruoyi.common.encrypt.core.EncryptorManager;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.AlgorithmType;
|
||||||
|
import com.ruoyi.common.encrypt.enumd.EncodeType;
|
||||||
|
import com.ruoyi.common.encrypt.properties.EncryptorProperties;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.ibatis.executor.parameter.ParameterHandler;
|
||||||
|
import org.apache.ibatis.plugin.Interceptor;
|
||||||
|
import org.apache.ibatis.plugin.Intercepts;
|
||||||
|
import org.apache.ibatis.plugin.Invocation;
|
||||||
|
import org.apache.ibatis.plugin.Signature;
|
||||||
|
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 入参加密拦截器
|
||||||
|
*
|
||||||
|
* @author 老马
|
||||||
|
* @version 4.6.0
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Intercepts({@Signature(
|
||||||
|
type = ParameterHandler.class,
|
||||||
|
method = "setParameters",
|
||||||
|
args = {PreparedStatement.class})
|
||||||
|
})
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class MybatisEncryptInterceptor implements Interceptor {
|
||||||
|
|
||||||
|
private final EncryptorManager encryptorManager;
|
||||||
|
private final EncryptorProperties defaultProperties;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object intercept(Invocation invocation) throws Throwable {
|
||||||
|
return invocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object plugin(Object target) {
|
||||||
|
if (target instanceof ParameterHandler) {
|
||||||
|
// 进行加密操作
|
||||||
|
ParameterHandler parameterHandler = (ParameterHandler) target;
|
||||||
|
Object parameterObject = parameterHandler.getParameterObject();
|
||||||
|
if (ObjectUtil.isNotNull(parameterObject) && !(parameterObject instanceof String)) {
|
||||||
|
this.encryptHandler(parameterObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密对象
|
||||||
|
*
|
||||||
|
* @param sourceObject 待加密对象
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked cast")
|
||||||
|
private void encryptHandler(Object sourceObject) {
|
||||||
|
if (sourceObject instanceof Map) {
|
||||||
|
((Map<?, Object>) sourceObject).values().forEach(this::encryptHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (sourceObject instanceof List) {
|
||||||
|
// 判断第一个元素是否含有注解。如果没有直接返回,提高效率
|
||||||
|
Object firstItem = ((List<?>) sourceObject).get(0);
|
||||||
|
if (CollectionUtil.isEmpty(encryptorManager.getFieldCache(firstItem.getClass()))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
((List<?>) sourceObject).forEach(this::encryptHandler);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Field> fields = encryptorManager.getFieldCache(sourceObject.getClass());
|
||||||
|
try {
|
||||||
|
for (Field field : fields) {
|
||||||
|
field.set(sourceObject, this.encryptField(String.valueOf(field.get(sourceObject)), field));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理加密字段时出错", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 字段值进行加密。通过字段的批注注册新的加密算法
|
||||||
|
*
|
||||||
|
* @param value 待加密的值
|
||||||
|
* @param field 待加密字段
|
||||||
|
* @return 加密后结果
|
||||||
|
*/
|
||||||
|
private String encryptField(String value, Field field) {
|
||||||
|
EncryptField encryptField = field.getAnnotation(EncryptField.class);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setProperties(Properties properties) {
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1 @@
|
|||||||
|
com.ruoyi.common.encrypt.config.EncryptorAutoConfiguration
|
||||||
Loading…
Reference in New Issue