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 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 originalFields = new HashMap<>(); extractSpecificSensitiveField(original, originalFields, fieldName, ""); // 提取更新对象中的指定敏感字段 Map updatedFields = new HashMap<>(); extractSpecificSensitiveField(updated, updatedFields, fieldName, ""); // 如果字段数量不同,说明有增删 if (originalFields.size() != updatedFields.size()) { return false; } // 比较每个字段的值 for (Map.Entry 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 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); } } } }