From f12d6677b898d41316bf894cccc7ce59a2c87c65 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=96=AF=E7=8B=82=E7=9A=84=E7=8B=AE=E5=AD=90Li?=
<15040126243@163.com>
Date: Wed, 17 Jan 2024 21:34:37 +0800
Subject: [PATCH] =?UTF-8?q?update=20=E4=BC=98=E5=8C=96=20=E4=BD=BF?=
=?UTF-8?q?=E7=94=A8=E9=A2=84=E6=89=AB=E6=8F=8F=E5=AE=9E=E4=BD=93=E7=B1=BB?=
=?UTF-8?q?=E6=8F=90=E5=8D=87=E4=BB=A3=E7=A0=81=E6=80=A7=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ruoyi-common/ruoyi-common-encrypt/pom.xml | 11 ++
.../config/EncryptorAutoConfiguration.java | 8 +-
.../common/encrypt/core/EncryptorManager.java | 100 ++++++++++++++----
.../MybatisDecryptInterceptor.java | 4 +
.../MybatisEncryptInterceptor.java | 4 +
5 files changed, 104 insertions(+), 23 deletions(-)
diff --git a/ruoyi-common/ruoyi-common-encrypt/pom.xml b/ruoyi-common/ruoyi-common-encrypt/pom.xml
index df3222be..baa59319 100644
--- a/ruoyi-common/ruoyi-common-encrypt/pom.xml
+++ b/ruoyi-common/ruoyi-common-encrypt/pom.xml
@@ -42,6 +42,17 @@
spring-webmvc
+
+ com.baomidou
+ mybatis-plus-spring-boot3-starter
+
+
+ org.mybatis
+ mybatis-spring
+
+
+
+
diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java
index e988a3a2..e7f2f3d7 100644
--- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java
+++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/config/EncryptorAutoConfiguration.java
@@ -1,5 +1,7 @@
package org.dromara.common.encrypt.config;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
+import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import org.dromara.common.encrypt.core.EncryptorManager;
import org.dromara.common.encrypt.interceptor.MybatisDecryptInterceptor;
import org.dromara.common.encrypt.interceptor.MybatisEncryptInterceptor;
@@ -16,7 +18,7 @@ import org.springframework.context.annotation.Bean;
* @author 老马
* @version 4.6.0
*/
-@AutoConfiguration
+@AutoConfiguration(after = MybatisPlusAutoConfiguration.class)
@EnableConfigurationProperties(EncryptorProperties.class)
@ConditionalOnProperty(value = "mybatis-encryptor.enable", havingValue = "true")
public class EncryptorAutoConfiguration {
@@ -25,8 +27,8 @@ public class EncryptorAutoConfiguration {
private EncryptorProperties properties;
@Bean
- public EncryptorManager encryptorManager() {
- return new EncryptorManager();
+ public EncryptorManager encryptorManager(MybatisPlusProperties mybatisPlusProperties) {
+ return new EncryptorManager(mybatisPlusProperties.getTypeAliasesPackage());
}
@Bean
diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java
index 782995d8..356b0436 100644
--- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java
+++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/core/EncryptorManager.java
@@ -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, Set> fieldCache = new ConcurrentHashMap<>();
+ /**
+ * 构造方法传入类加密字段缓存
+ *
+ * @param typeAliasesPackage 实体类包
+ */
+ public EncryptorManager(String typeAliasesPackage) {
+ this.fieldCache = scanEncryptClasses(typeAliasesPackage);
+ }
+
+
/**
* 获取类加密字段缓存
*/
public Set getFieldCache(Class> sourceClazz) {
- return fieldCache.computeIfAbsent(sourceClazz, clazz -> {
- Set 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, Set> scanEncryptClasses(String typeAliasesPackage) {
+ Map, Set> 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 encryptFieldSet = getEncryptFieldSetFromClazz(clazz);
+ if (CollUtil.isNotEmpty(encryptFieldSet)) {
+ fieldCache.put(clazz, encryptFieldSet);
+ }
+ }
+ }
+ } catch (Exception e) {
+ log.error("初始化数据安全缓存时出错:{}", e.getMessage());
+ }
+ return fieldCache;
+ }
+
+ /**
+ * 获得一个类的加密字段集合
+ */
+ private Set getEncryptFieldSetFromClazz(Class> clazz) {
+ Set 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;
+ }
+
}
diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java
index 7c2508f8..460aa360 100644
--- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java
+++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisDecryptInterceptor.java
@@ -73,7 +73,11 @@ public class MybatisDecryptInterceptor implements Interceptor {
list.forEach(this::decryptHandler);
return;
}
+ // 不在缓存中的类,就是没有加密注解的类(当然也有可能是typeAliasesPackage写错)
Set fields = encryptorManager.getFieldCache(sourceObject.getClass());
+ if(ObjectUtil.isNull(fields)){
+ return;
+ }
try {
for (Field field : fields) {
field.set(sourceObject, this.decryptField(Convert.toStr(field.get(sourceObject)), field));
diff --git a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java
index 152f7db4..bcc2f4c9 100644
--- a/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java
+++ b/ruoyi-common/ruoyi-common-encrypt/src/main/java/org/dromara/common/encrypt/interceptor/MybatisEncryptInterceptor.java
@@ -82,7 +82,11 @@ public class MybatisEncryptInterceptor implements Interceptor {
list.forEach(this::encryptHandler);
return;
}
+ // 不在缓存中的类,就是没有加密注解的类(当然也有可能是typeAliasesPackage写错)
Set fields = encryptorManager.getFieldCache(sourceObject.getClass());
+ if(ObjectUtil.isNull(fields)){
+ return;
+ }
try {
for (Field field : fields) {
field.set(sourceObject, this.encryptField(Convert.toStr(field.get(sourceObject)), field));