package xiaozhi.common.utils;
|
|
import java.util.Arrays;
|
import java.util.HashMap;
|
import java.util.HashSet;
|
import java.util.Map;
|
import java.util.Set;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import cn.hutool.json.JSONObject;
|
|
/**
|
* 敏感数据处理工具类
|
*/
|
public class SensitiveDataUtils {
|
|
// 敏感字段列表
|
private static final Set<String> SENSITIVE_FIELDS = new HashSet<>(Arrays.asList(
|
"api_key", "personal_access_token", "access_token", "token",
|
"secret", "access_key_secret", "secret_key"));
|
|
/**
|
* 检查字段是否为敏感字段
|
*/
|
public static boolean isSensitiveField(String fieldName) {
|
return StringUtils.isNotBlank(fieldName) && SENSITIVE_FIELDS.contains(fieldName.toLowerCase());
|
}
|
|
/**
|
* 隐藏字符串中间部分
|
*/
|
public static String maskMiddle(String value) {
|
if (StringUtils.isBlank(value) || value.length() == 1) {
|
return value;
|
}
|
|
int length = value.length();
|
if (length <= 8) {
|
// 短字符串保留前2后2
|
return value.substring(0, 2) + "****" + value.substring(length - 2);
|
} else {
|
// 长字符串保留前4后4
|
int maskLength = length - 8;
|
StringBuilder maskBuilder = new StringBuilder();
|
for (int i = 0; i < maskLength; i++) {
|
maskBuilder.append('*');
|
}
|
return value.substring(0, 4) + maskBuilder.toString() + value.substring(length - 4);
|
}
|
}
|
|
/**
|
* 判断字符串是否是被掩码处理过的值
|
*/
|
public static boolean isMaskedValue(String value) {
|
if (StringUtils.isBlank(value)) {
|
return false;
|
}
|
// 掩码值至少包含4个连续的*
|
return value.contains("****");
|
}
|
|
/**
|
* 处理JSONObject中的敏感字段
|
*/
|
public static JSONObject maskSensitiveFields(JSONObject jsonObject) {
|
if (jsonObject == null) {
|
return null;
|
}
|
|
JSONObject result = new JSONObject();
|
|
for (String key : jsonObject.keySet()) {
|
Object value = jsonObject.get(key);
|
|
if (SENSITIVE_FIELDS.contains(key.toLowerCase()) && value instanceof String) {
|
result.set(key, maskMiddle((String) value));
|
} else if (value instanceof JSONObject) {
|
result.set(key, maskSensitiveFields((JSONObject) value));
|
} else {
|
result.set(key, value);
|
}
|
}
|
|
return result;
|
}
|
|
/**
|
* 比较两个JSONObject的敏感字段是否相同
|
* 特别针对api_key等敏感字段进行单独比较
|
*/
|
public static boolean isSensitiveDataEqual(JSONObject original, JSONObject updated) {
|
if (original == null && updated == null) {
|
return true;
|
}
|
if (original == null || updated == null) {
|
return false;
|
}
|
|
// 提取并比较特定敏感字段
|
return compareSpecificSensitiveFields(original, updated, "api_key") &&
|
compareSpecificSensitiveFields(original, updated, "personal_access_token") &&
|
compareSpecificSensitiveFields(original, updated, "access_token") &&
|
compareSpecificSensitiveFields(original, updated, "token") &&
|
compareSpecificSensitiveFields(original, updated, "secret") &&
|
compareSpecificSensitiveFields(original, updated, "access_key_secret") &&
|
compareSpecificSensitiveFields(original, updated, "secret_key");
|
}
|
|
/**
|
* 比较两个JSON对象中特定敏感字段是否相同
|
* 遍历整个JSON对象树,查找并比较指定敏感字段
|
*/
|
private static boolean compareSpecificSensitiveFields(JSONObject original, JSONObject updated, String fieldName) {
|
// 提取原始对象中的指定敏感字段
|
Map<String, String> originalFields = new HashMap<>();
|
extractSpecificSensitiveField(original, originalFields, fieldName, "");
|
|
// 提取更新对象中的指定敏感字段
|
Map<String, String> updatedFields = new HashMap<>();
|
extractSpecificSensitiveField(updated, updatedFields, fieldName, "");
|
|
// 如果字段数量不同,说明有增删
|
if (originalFields.size() != updatedFields.size()) {
|
return false;
|
}
|
|
// 比较每个字段的值
|
for (Map.Entry<String, String> entry : originalFields.entrySet()) {
|
String key = entry.getKey();
|
String originalValue = entry.getValue();
|
String updatedValue = updatedFields.get(key);
|
|
if (updatedValue == null || !updatedValue.equals(originalValue)) {
|
return false;
|
}
|
}
|
|
return true;
|
}
|
|
/**
|
* 递归提取JSON对象中指定名称的敏感字段
|
*/
|
private static void extractSpecificSensitiveField(JSONObject jsonObject, Map<String, String> fieldsMap,
|
String targetFieldName, String parentPath) {
|
if (jsonObject == null) {
|
return;
|
}
|
|
for (String key : jsonObject.keySet()) {
|
String fullPath = parentPath.isEmpty() ? key : parentPath + "." + key;
|
Object value = jsonObject.get(key);
|
|
if (value instanceof JSONObject) {
|
// 递归处理嵌套JSON对象
|
extractSpecificSensitiveField((JSONObject) value, fieldsMap, targetFieldName, fullPath);
|
} else if (value instanceof String && key.equalsIgnoreCase(targetFieldName)) {
|
// 找到目标敏感字段,保存其路径和值
|
fieldsMap.put(fullPath, (String) value);
|
}
|
}
|
}
|
}
|