update 优化 重构 !pr274 简化结构 解决代码逻辑问题 规范注释

This commit is contained in:
疯狂的狮子li
2023-01-18 14:11:48 +08:00
parent e20dacbfd9
commit d2675744f4
24 changed files with 339 additions and 409 deletions

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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<Class<?>, Set<Field>> ENCRYPTED_FIELD_CACHE = new ConcurrentHashMap<>();
public static Set<Field> get(Class<?> sourceClazz) {
return ENCRYPTED_FIELD_CACHE.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;
});
}
}

View File

@ -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<String, IEncryptor> 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());
}
}

View File

@ -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<Field> fields = EncryptedFieldsCache.get(sourceObject.getClass());
Set<Field> 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

View File

@ -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<?, Object>) 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<Field> fields = EncryptedFieldsCache.get(sourceObject.getClass());
Set<Field> 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);
}

View File

@ -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<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);
}
}