This commit is contained in:
zhangwenzan 2025-09-04 09:31:10 +08:00
parent fc79b80e69
commit 0c99c66172
3 changed files with 178 additions and 9 deletions

View File

@ -21,7 +21,6 @@ public class EsDataEncryptUtil {
private static final Set<String> 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);
@ -63,7 +62,7 @@ public class EsDataEncryptUtil {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
decryptedMap.put(key, decryptValue(value));
decryptedMap.put(key, decryptValue(key,value));
}
return decryptedMap;
}
@ -133,7 +132,7 @@ public class EsDataEncryptUtil {
* 根据值类型进行解密
*/
@SuppressWarnings("unchecked")
private static Object decryptValue(Object value) {
private static Object decryptValue(String key,Object value) {
if (value == null) {
return null;
}
@ -142,7 +141,8 @@ public class EsDataEncryptUtil {
String strValue = (String) value;
// 对已加密的数据进行解密
if (strValue.startsWith(Const.ENCRYPTED_PREFIX)) {
return getEncryptionService().decryptAes(strValue.substring(Const.ENCRYPTED_PREFIX.length()));
String newValue = getEncryptionService().decryptAes(strValue.substring(Const.ENCRYPTED_PREFIX.length()));
return desensitization(key,newValue);
}
return strValue;
} else if (value instanceof Map) {
@ -152,7 +152,7 @@ public class EsDataEncryptUtil {
// 递归处理List中的每个元素
List<Object> decryptedList = new ArrayList<>();
for (Object item : (List<Object>) value) {
decryptedList.add(decryptValue(item));
decryptedList.add(decryptValue(key,item));
}
return decryptedList;
}
@ -160,6 +160,19 @@ public class EsDataEncryptUtil {
return value;
}
// 数据脱敏
private static String desensitization(String key,String value){
if ("mobile".equals(key)) {
return SensitiveDataMaskUtil.maskPhone(value);
}else if ("email".equals(key)) {
return SensitiveDataMaskUtil.maskEmail(value);
}else if ("ownerDeptName".equals(key)) {
return SensitiveDataMaskUtil.maskName(value);
}else if ("address".equals(key)) {
return SensitiveDataMaskUtil.maskAddress(value);
}
return value;
}
/**
* 判断字段是否为日期类型字段
* @param fieldName 字段名

View File

@ -0,0 +1,150 @@
package com.kakarote.core.security.util;
import org.apache.commons.lang3.StringUtils;
/**
* 敏感数据脱敏工具类
* 提供姓名手机号地址等敏感信息的脱敏处理
*/
public class SensitiveDataMaskUtil {
/**
* 对姓名进行脱敏处理
* 规则
* 1. 单字名显示姓氏其余用*代替
* 2. 双字名显示姓氏名用*代替
* 3. 多字名显示姓氏和最后一个字中间用*代替
* 4. 长度不足的情况直接返回原字符串
*
* @param name 姓名
* @return 脱敏后的姓名
*/
public static String maskName(String name) {
if (StringUtils.isBlank(name)) {
return StringUtils.EMPTY;
}
int length = name.length();
if (length == 1) {
// 单字名直接返回
return name;
} else if (length == 2) {
// 双字名显示姓氏
return name.charAt(0) + "*";
} else if (length == 3) {
// 三字名显示姓氏和最后一个字
return name.charAt(0) + "*" + name.charAt(2);
} else {
// 多字名显示姓氏和最后一个字中间用*代替
return name.charAt(0) + StringUtils.repeat("*", length - 2) + name.charAt(length - 1);
}
}
/**
* 对手机号码进行脱敏处理
* 规则保留前3位和后4位中间用*代替
*
* @param phone 手机号码
* @return 脱敏后的手机号码
*/
public static String maskPhone(String phone) {
if (StringUtils.isBlank(phone) || phone.length() < 11) {
return phone;
}
return phone.substring(0, 3) + "****" + phone.substring(7);
}
/**
* 对地址进行脱敏处理
* 规则
* 1. 保留省后面的详细地址用*代替
* 2. 如果地址较短保留前8个字符后面用*代替
*
* @param address 地址
* @return 脱敏后的地址
*/
public static String maskAddress(String address) {
if (StringUtils.isBlank(address)) {
return StringUtils.EMPTY;
}
int length = address.length();
if (length <= 8) {
// 地址较短保留前半部分
int keepLength = Math.max(1, length / 2);
return address.substring(0, keepLength) + StringUtils.repeat("*", length - keepLength);
} else {
// 地址较长保留前8个字符
return address.substring(0, 8) + "****";
}
}
/**
* 对邮箱进行脱敏处理
* 规则保留前2位和域名中间用*代替
*
* @param email 邮箱地址
* @return 脱敏后的邮箱
*/
public static String maskEmail(String email) {
if (StringUtils.isBlank(email) || !email.contains("@")) {
return email;
}
String[] parts = email.split("@");
if (parts.length != 2) {
return email;
}
String username = parts[0];
String domain = parts[1];
if (username.length() <= 2) {
// 用户名较短全部用*代替
return StringUtils.repeat("*", username.length()) + "@" + domain;
} else {
// 保留前2位其余用*代替
return username.substring(0, 2) + StringUtils.repeat("*", username.length() - 2) + "@" + domain;
}
}
/**
* 对身份证号进行脱敏处理
* 规则保留前6位和后4位中间用*代替
*
* @param idCard 身份证号
* @return 脱敏后的身份证号
*/
public static String maskIdCard(String idCard) {
if (StringUtils.isBlank(idCard) || idCard.length() < 18) {
return idCard;
}
return idCard.substring(0, 6) + StringUtils.repeat("*", 8) + idCard.substring(14);
}
/**
* 通用脱敏方法
*
* @param str 原始字符串
* @param start 保留的开始位置包含
* @param end 保留的结束位置包含
* @return 脱敏后的字符串
*/
public static String maskGeneral(String str, int start, int end) {
if (StringUtils.isBlank(str)) {
return StringUtils.EMPTY;
}
int length = str.length();
if (start < 0 || end < 0 || start >= length || end >= length || start >= end) {
return str;
}
StringBuilder sb = new StringBuilder();
sb.append(str.substring(0, start));
sb.append(StringUtils.repeat("*", end - start + 1));
sb.append(str.substring(end + 1));
return sb.toString();
}
}

View File

@ -12,6 +12,7 @@ import com.kakarote.core.common.SystemCodeEnum;
import com.kakarote.core.exception.CrmException;
import com.kakarote.core.feign.admin.entity.SimpleUser;
import com.kakarote.core.field.FieldService;
import com.kakarote.core.security.util.EsDataEncryptUtil;
import com.kakarote.core.servlet.ApplicationContextHolder;
import com.kakarote.core.utils.UserCacheUtil;
import com.kakarote.crm.constant.CrmEnum;
@ -458,10 +459,12 @@ public class InitEsIndexRunner implements ApplicationRunner {
}
}
});
// 在创建IndexRequest之前加密数据
Map<String, Object> encryptedMap = EsDataEncryptUtil.encryptMap(map);
IndexRequest request = new IndexRequest(crmEnum.getIndex(), "_doc");
request.id(map.get(crmEnum.getPrimaryKey()).toString());
request.source(map);
request.id(encryptedMap.get(crmEnum.getPrimaryKey()).toString());
request.source(encryptedMap);
bulkRequest.add(request);
if (bulkRequest.requests().size() >= 1000) {
bulk(bulkRequest);
@ -510,7 +513,10 @@ public class InitEsIndexRunner implements ApplicationRunner {
}
}
}
request.doc(map);
// 在创建UpdateRequest之前加密数据
Map<String, Object> encryptedMap = EsDataEncryptUtil.encryptMap(map);
request.doc(encryptedMap);
bulkRequest.add(request);
if (bulkRequest.requests().size() >= 1000) {
bulk(bulkRequest);