|
|
|
@ -1,14 +1,23 @@
|
|
|
|
|
package org.dromara.common.encrypt.core;
|
|
|
|
|
|
|
|
|
|
import cn.hutool.core.collection.CollUtil;
|
|
|
|
|
import cn.hutool.core.util.ObjectUtil;
|
|
|
|
|
import cn.hutool.core.util.ReflectUtil;
|
|
|
|
|
import org.dromara.common.encrypt.annotation.EncryptField;
|
|
|
|
|
import lombok.NoArgsConstructor;
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
import org.apache.ibatis.io.Resources;
|
|
|
|
|
import org.dromara.common.core.utils.StringUtils;
|
|
|
|
|
import org.dromara.common.encrypt.annotation.EncryptField;
|
|
|
|
|
import org.springframework.context.ConfigurableApplicationContext;
|
|
|
|
|
import org.springframework.core.io.Resource;
|
|
|
|
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
|
|
|
|
import org.springframework.core.io.support.ResourcePatternResolver;
|
|
|
|
|
import org.springframework.core.type.ClassMetadata;
|
|
|
|
|
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
|
|
|
|
|
import org.springframework.util.ClassUtils;
|
|
|
|
|
|
|
|
|
|
import java.lang.reflect.Field;
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
import java.util.Map;
|
|
|
|
|
import java.util.Set;
|
|
|
|
|
import java.util.*;
|
|
|
|
|
import java.util.concurrent.ConcurrentHashMap;
|
|
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
@ -19,6 +28,7 @@ import java.util.stream.Collectors;
|
|
|
|
|
* @version 4.6.0
|
|
|
|
|
*/
|
|
|
|
|
@Slf4j
|
|
|
|
|
@NoArgsConstructor
|
|
|
|
|
public class EncryptorManager {
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -31,25 +41,24 @@ public class EncryptorManager {
|
|
|
|
|
*/
|
|
|
|
|
Map<Class<?>, Set<Field>> fieldCache = new ConcurrentHashMap<>();
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 构造方法传入类加密字段缓存
|
|
|
|
|
*
|
|
|
|
|
* @param typeAliasesPackage 实体类包
|
|
|
|
|
*/
|
|
|
|
|
public EncryptorManager(String typeAliasesPackage) {
|
|
|
|
|
this.fieldCache = scanEncryptClasses(typeAliasesPackage);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取类加密字段缓存
|
|
|
|
|
*/
|
|
|
|
|
public Set<Field> getFieldCache(Class<?> sourceClazz) {
|
|
|
|
|
return fieldCache.computeIfAbsent(sourceClazz, clazz -> {
|
|
|
|
|
Set<Field> fieldSet = new HashSet<>();
|
|
|
|
|
while (clazz != null) {
|
|
|
|
|
Field[] fields = clazz.getDeclaredFields();
|
|
|
|
|
fieldSet.addAll(Arrays.asList(fields));
|
|
|
|
|
clazz = clazz.getSuperclass();
|
|
|
|
|
}
|
|
|
|
|
fieldSet = fieldSet.stream().filter(field ->
|
|
|
|
|
field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class)
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
for (Field field : fieldSet) {
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
}
|
|
|
|
|
return fieldSet;
|
|
|
|
|
});
|
|
|
|
|
if (ObjectUtil.isNotNull(fieldCache)) {
|
|
|
|
|
return fieldCache.get(sourceClazz);
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
@ -97,4 +106,55 @@ public class EncryptorManager {
|
|
|
|
|
return encryptor.decrypt(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 通过 typeAliasesPackage 设置的扫描包 扫描缓存实体
|
|
|
|
|
*/
|
|
|
|
|
private Map<Class<?>, Set<Field>> scanEncryptClasses(String typeAliasesPackage) {
|
|
|
|
|
Map<Class<?>, Set<Field>> fieldCache = new HashMap<>();
|
|
|
|
|
PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
|
|
|
|
|
CachingMetadataReaderFactory factory = new CachingMetadataReaderFactory();
|
|
|
|
|
String[] packagePatternArray = StringUtils.splitPreserveAllTokens(typeAliasesPackage, ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);
|
|
|
|
|
String classpath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX;
|
|
|
|
|
try {
|
|
|
|
|
for (String packagePattern : packagePatternArray) {
|
|
|
|
|
String path = ClassUtils.convertClassNameToResourcePath(packagePattern);
|
|
|
|
|
Resource[] resources = resolver.getResources(classpath + path + "/*.class");
|
|
|
|
|
for (Resource resource : resources) {
|
|
|
|
|
ClassMetadata classMetadata = factory.getMetadataReader(resource).getClassMetadata();
|
|
|
|
|
Class<?> clazz = Resources.classForName(classMetadata.getClassName());
|
|
|
|
|
Set<Field> encryptFieldSet = getEncryptFieldSetFromClazz(clazz);
|
|
|
|
|
if (CollUtil.isNotEmpty(encryptFieldSet)) {
|
|
|
|
|
fieldCache.put(clazz, encryptFieldSet);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} catch (Exception e) {
|
|
|
|
|
log.error("初始化数据安全缓存时出错:{}", e.getMessage());
|
|
|
|
|
}
|
|
|
|
|
return fieldCache;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获得一个类的加密字段集合
|
|
|
|
|
*/
|
|
|
|
|
private Set<Field> getEncryptFieldSetFromClazz(Class<?> clazz) {
|
|
|
|
|
Set<Field> fieldSet = new HashSet<>();
|
|
|
|
|
// 判断clazz如果是接口,内部类,匿名类就直接返回
|
|
|
|
|
if (clazz.isInterface() || clazz.isMemberClass() || clazz.isAnonymousClass()) {
|
|
|
|
|
return fieldSet;
|
|
|
|
|
}
|
|
|
|
|
while (clazz != null) {
|
|
|
|
|
Field[] fields = clazz.getDeclaredFields();
|
|
|
|
|
fieldSet.addAll(Arrays.asList(fields));
|
|
|
|
|
clazz = clazz.getSuperclass();
|
|
|
|
|
}
|
|
|
|
|
fieldSet = fieldSet.stream().filter(field ->
|
|
|
|
|
field.isAnnotationPresent(EncryptField.class) && field.getType() == String.class)
|
|
|
|
|
.collect(Collectors.toSet());
|
|
|
|
|
for (Field field : fieldSet) {
|
|
|
|
|
field.setAccessible(true);
|
|
|
|
|
}
|
|
|
|
|
return fieldSet;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|