From fc79b80e69ad90093f1830d08911c0280c818663 Mon Sep 17 00:00:00 2001 From: zhangwenzan Date: Thu, 28 Aug 2025 15:26:06 +0800 Subject: [PATCH] =?UTF-8?q?es=E5=8A=A0=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/security/util/EsDataEncryptUtil.java | 177 ++++++++++++++++++ .../com/kakarote/crm/common/ElasticUtil.java | 18 +- .../kakarote/crm/service/CrmPageService.java | 12 +- 3 files changed, 202 insertions(+), 5 deletions(-) create mode 100644 core/src/main/java/com/kakarote/core/security/util/EsDataEncryptUtil.java diff --git a/core/src/main/java/com/kakarote/core/security/util/EsDataEncryptUtil.java b/core/src/main/java/com/kakarote/core/security/util/EsDataEncryptUtil.java new file mode 100644 index 0000000..2d8d3e9 --- /dev/null +++ b/core/src/main/java/com/kakarote/core/security/util/EsDataEncryptUtil.java @@ -0,0 +1,177 @@ +package com.kakarote.core.security.util; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import com.kakarote.core.common.Const; +import com.kakarote.core.common.FieldEnum; +import com.kakarote.core.security.EncryptionService; +import com.kakarote.core.servlet.ApplicationContextHolder; +import org.springframework.util.CollectionUtils; + +import java.util.*; + +/** + * Elasticsearch数据加密解密工具类 + */ +public class EsDataEncryptUtil { + + private static EncryptionService encryptionService; + + // 日期类型字段的前缀列表,可根据实际情况扩展 + private static final Set DATE_FIELD_PREFIXES = new HashSet<>(Arrays.asList( + "createTime", "updateTime", "lastTime", "startTime", "endTime", "birthDate", "nextContactTime" + )); + + private static EncryptionService getEncryptionService() { + if (encryptionService == null) { + encryptionService = ApplicationContextHolder.getBean(EncryptionService.class); + } + return encryptionService; + } + + /** + * 加密Map中的所有String类型字段,但跳过日期类型字段 + */ + public static Map encryptMap(Map map) { + if (map == null || map.isEmpty()) { + return map; + } + + Map encryptedMap = new HashMap<>(map.size()); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + // 检查是否为日期类型字段,如果是则不加密 + if (isDateField(key) && value instanceof String) { + encryptedMap.put(key, value); + } else { + encryptedMap.put(key, encryptValue(value)); + } + } + return encryptedMap; + } + + /** + * 解密Map中的所有字段 + */ + public static Map decryptMap(Map map) { + if (map == null || map.isEmpty()) { + return map; + } + + Map decryptedMap = new HashMap<>(map.size()); + for (Map.Entry entry : map.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + decryptedMap.put(key, decryptValue(value)); + } + return decryptedMap; + } + + /** + * 加密List中每个Map的所有字段 + */ + public static List> encryptMapList(List> list) { + if (CollectionUtils.isEmpty(list)) { + return list; + } + + List> encryptedList = new ArrayList<>(list.size()); + for (Map map : list) { + encryptedList.add(encryptMap(map)); + } + return encryptedList; + } + + /** + * 解密List中每个Map的所有字段 + */ + public static List> decryptMapList(List> list) { + if (CollectionUtils.isEmpty(list)) { + return list; + } + + List> decryptedList = new ArrayList<>(list.size()); + for (Map map : list) { + decryptedList.add(decryptMap(map)); + } + return decryptedList; + } + + /** + * 根据值类型进行加密 + */ + @SuppressWarnings("unchecked") + private static Object encryptValue(Object value) { + if (value == null) { + return null; + } + + if (value instanceof String) { + String strValue = (String) value; + // 已经加密的不再重复加密 + if (!strValue.isEmpty() && !strValue.startsWith(Const.ENCRYPTED_PREFIX)) { + return Const.ENCRYPTED_PREFIX + getEncryptionService().encryptAes(strValue); + } + return strValue; + } else if (value instanceof Map) { + // 递归处理嵌套Map + return encryptMap((Map) value); + } else if (value instanceof List) { + // 递归处理List中的每个元素 + List encryptedList = new ArrayList<>(); + for (Object item : (List) value) { + encryptedList.add(encryptValue(item)); + } + return encryptedList; + } + // 其他类型保持不变 + return value; + } + + /** + * 根据值类型进行解密 + */ + @SuppressWarnings("unchecked") + private static Object decryptValue(Object value) { + if (value == null) { + return null; + } + + if (value instanceof String) { + String strValue = (String) value; + // 对已加密的数据进行解密 + if (strValue.startsWith(Const.ENCRYPTED_PREFIX)) { + return getEncryptionService().decryptAes(strValue.substring(Const.ENCRYPTED_PREFIX.length())); + } + return strValue; + } else if (value instanceof Map) { + // 递归处理嵌套Map + return decryptMap((Map) value); + } else if (value instanceof List) { + // 递归处理List中的每个元素 + List decryptedList = new ArrayList<>(); + for (Object item : (List) value) { + decryptedList.add(decryptValue(item)); + } + return decryptedList; + } + // 其他类型保持不变 + return value; + } + + /** + * 判断字段是否为日期类型字段 + * @param fieldName 字段名 + * @return 是否为日期类型字段 + */ + private static boolean isDateField(String fieldName) { + // 检查字段名是否以日期字段前缀开头 + for (String prefix : DATE_FIELD_PREFIXES) { + if (fieldName.equals(prefix) || fieldName.endsWith("Time") || fieldName.endsWith("Date")) { + return true; + } + } + return false; + } +} \ No newline at end of file diff --git a/crm/src/main/java/com/kakarote/crm/common/ElasticUtil.java b/crm/src/main/java/com/kakarote/crm/common/ElasticUtil.java index 0b22cdf..fc193af 100644 --- a/crm/src/main/java/com/kakarote/crm/common/ElasticUtil.java +++ b/crm/src/main/java/com/kakarote/crm/common/ElasticUtil.java @@ -8,11 +8,14 @@ import cn.hutool.core.util.StrUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.google.common.collect.Lists; +import com.kakarote.core.common.Const; import com.kakarote.core.common.FieldEnum; import com.kakarote.core.common.JxcEnum; import com.kakarote.core.common.SystemCodeEnum; import com.kakarote.core.exception.CrmException; import com.kakarote.core.feign.crm.entity.BiParams; +import com.kakarote.core.security.EncryptionService; +import com.kakarote.core.security.util.EsDataEncryptUtil; import com.kakarote.core.servlet.ApplicationContextHolder; import com.kakarote.core.utils.BiTimeUtil; import com.kakarote.crm.constant.CrmEnum; @@ -249,7 +252,16 @@ public class ElasticUtil { BulkRequest bulkRequest = new BulkRequest(); ids.forEach(id -> { Map map = new HashMap<>(); - map.put(fieldName, value); + if (value instanceof String) { + String strValue = (String) value; + if (!strValue.isEmpty() && !strValue.startsWith(Const.ENCRYPTED_PREFIX)) { + map.put(fieldName, Const.ENCRYPTED_PREFIX + ApplicationContextHolder.getBean(EncryptionService.class).encryptAes(strValue)); + } else { + map.put(fieldName, value); + } + } else { + map.put(fieldName, value); + } UpdateRequest request = new UpdateRequest(index, "_doc", id.toString()); request.doc(map); bulkRequest.add(request); @@ -269,8 +281,10 @@ public class ElasticUtil { */ public static void updateField(ElasticsearchRestTemplate template, Map map, Integer id, String index) { try { + // 加密字段值 + Map encryptedMap = EsDataEncryptUtil.encryptMap(map); UpdateRequest request = new UpdateRequest(index, "_doc", id.toString()); - request.doc(map); + request.doc(encryptedMap); template.getClient().update(request, RequestOptions.DEFAULT); template.refresh(index); } catch (IOException e) { diff --git a/crm/src/main/java/com/kakarote/crm/service/CrmPageService.java b/crm/src/main/java/com/kakarote/crm/service/CrmPageService.java index 58af31d..43234b3 100644 --- a/crm/src/main/java/com/kakarote/crm/service/CrmPageService.java +++ b/crm/src/main/java/com/kakarote/crm/service/CrmPageService.java @@ -26,6 +26,7 @@ import com.kakarote.core.feign.admin.service.AdminService; import com.kakarote.core.feign.examine.entity.ExamineRecordSaveBO; import com.kakarote.core.field.FieldService; import com.kakarote.core.redis.Redis; +import com.kakarote.core.security.util.EsDataEncryptUtil; import com.kakarote.core.servlet.ApplicationContextHolder; import com.kakarote.core.servlet.BaseService; import com.kakarote.core.servlet.upload.FileEntity; @@ -124,8 +125,9 @@ public interface CrmPageService { } for (SearchHit hit : hits) { Map sourceAsMap = hit.getSourceAsMap(); - sourceAsMap.put(getLabel().getPrimaryKey(), Integer.valueOf(hit.getId())); - mapList.add(parseMap(sourceAsMap, voList)); + Map decryptedMap = EsDataEncryptUtil.decryptMap(sourceAsMap); + decryptedMap.put(getLabel().getPrimaryKey(), Integer.valueOf(hit.getId())); + mapList.add(parseMap(decryptedMap, voList)); } BasePage> basePage = new BasePage<>(); ApplicationContextHolder.getBean(ICrmRoleFieldService.class).replaceMaskFieldValue(getLabel(),mapList,1); @@ -669,8 +671,12 @@ public interface CrmPageService { map.put("ownerDeptId",simpleUser.getDeptId()); map.put("ownerDeptName",simpleUser.getDeptName()); } + + // 加密所有字段 + Map encryptedMap = EsDataEncryptUtil.encryptMap(map); + UpdateRequest request = new UpdateRequest(getIndex(), getDocType(),id.toString()); - request.doc(map); + request.doc(encryptedMap); request.docAsUpsert(true); try { getRestTemplate().getClient().update(request, RequestOptions.DEFAULT);