package com.dsh.guns.modular.system.audit;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONArray;
|
import com.alibaba.fastjson.JSONObject;
|
import io.swagger.annotations.ApiModelProperty;
|
import cn.mb.cloud.common.core.util.SpringContextHolder;
|
|
import java.lang.reflect.Field;
|
import java.util.LinkedHashMap;
|
import java.util.Map;
|
|
/** 审计数据统一脱敏并将常用字段名转换为中文,供日志页面直接展示。 */
|
public final class AuditDataFormatter {
|
private static final Map<String, String> FIELD_NAMES = new LinkedHashMap<String, String>();
|
static {
|
FIELD_NAMES.put("id", "ID"); FIELD_NAMES.put("ids", "ID列表");
|
FIELD_NAMES.put("name", "名称"); FIELD_NAMES.put("username", "用户名"); FIELD_NAMES.put("userName", "用户名");
|
FIELD_NAMES.put("account", "账号"); FIELD_NAMES.put("phone", "手机号"); FIELD_NAMES.put("mobile", "手机号");
|
FIELD_NAMES.put("password", "密码"); FIELD_NAMES.put("oldPwd", "旧密码"); FIELD_NAMES.put("newPwd", "新密码");
|
FIELD_NAMES.put("idCard", "身份证号"); FIELD_NAMES.put("identity", "身份信息");
|
FIELD_NAMES.put("status", "状态"); FIELD_NAMES.put("state", "状态"); FIELD_NAMES.put("type", "类型");
|
FIELD_NAMES.put("birthday", "生日"); FIELD_NAMES.put("sex", "性别"); FIELD_NAMES.put("roleid", "角色ID");
|
FIELD_NAMES.put("deptid", "部门ID"); FIELD_NAMES.put("avatar", "头像"); FIELD_NAMES.put("jstime", "入职时间");
|
FIELD_NAMES.put("email", "邮箱"); FIELD_NAMES.put("objectType", "归属类型"); FIELD_NAMES.put("objectId", "归属对象ID");
|
FIELD_NAMES.put("remark", "备注"); FIELD_NAMES.put("reason", "原因"); FIELD_NAMES.put("content", "内容");
|
FIELD_NAMES.put("operatorId", "运营商ID"); FIELD_NAMES.put("storeId", "门店ID");
|
FIELD_NAMES.put("userId", "用户ID"); FIELD_NAMES.put("roleId", "角色ID"); FIELD_NAMES.put("roleIds", "角色ID列表");
|
FIELD_NAMES.put("cityId", "城市ID"); FIELD_NAMES.put("courseId", "课程ID");
|
FIELD_NAMES.put("createdAt", "创建时间"); FIELD_NAMES.put("updateTime", "更新时间");
|
}
|
|
private AuditDataFormatter() { }
|
|
public static String format(Object value) {
|
return format(value, null);
|
}
|
|
/** entityType 非空时,字段中文名完全由实体注解决定。 */
|
public static String format(Object value, Class<?> entityType) {
|
if (value == null) return null;
|
Object json = value instanceof String ? parse((String) value) : JSON.toJSON(value);
|
return mask(JSON.toJSONString(localize(json, entityType)));
|
}
|
|
private static Object parse(String value) {
|
try { return JSON.parse(value); } catch (Exception ignored) { return value; }
|
}
|
|
private static Object localize(Object value, Class<?> entityType) {
|
if (value instanceof JSONObject) {
|
JSONObject source = (JSONObject) value;
|
JSONObject target = new JSONObject(true);
|
for (Map.Entry<String, Object> entry : source.entrySet()) {
|
target.put(displayName(entry.getKey(), entityType), localize(entry.getValue(), null));
|
}
|
return target;
|
}
|
if (value instanceof Map) {
|
JSONObject target = new JSONObject(true);
|
for (Object item : ((Map<?, ?>) value).entrySet()) {
|
Map.Entry<?, ?> entry = (Map.Entry<?, ?>) item;
|
target.put(displayName(String.valueOf(entry.getKey()), entityType), localize(entry.getValue(), null));
|
}
|
return target;
|
}
|
if (value instanceof JSONArray) {
|
JSONArray target = new JSONArray();
|
for (Object item : (JSONArray) value) target.add(localize(item, null));
|
return target;
|
}
|
return value;
|
}
|
|
private static String displayName(String field, Class<?> entityType) {
|
String annotated = annotationName(entityType, field);
|
if (annotated != null) return annotated;
|
String name = FIELD_NAMES.get(field);
|
return name == null ? field : name;
|
}
|
|
private static String annotationName(Class<?> entityType, String fieldName) {
|
if (entityType == null) return null;
|
for (Class<?> type = entityType; type != null && type != Object.class; type = type.getSuperclass()) {
|
try {
|
Field field = type.getDeclaredField(fieldName);
|
AuditField audit = field.getAnnotation(AuditField.class);
|
if (audit != null) return audit.value();
|
ApiModelProperty api = field.getAnnotation(ApiModelProperty.class);
|
if (api != null && api.value() != null && !api.value().trim().isEmpty()) return api.value();
|
} catch (NoSuchFieldException ignored) { }
|
}
|
try {
|
String comment = SpringContextHolder.getBean(AuditColumnCommentResolver.class).resolve(entityType).get(fieldName);
|
if (comment != null && !comment.trim().isEmpty()) return comment;
|
} catch (Exception ignored) {
|
// 审计展示名解析失败时回退字段名,不能影响业务。
|
}
|
return null;
|
}
|
|
private static String mask(String text) {
|
return text.replaceAll("(?i)(\\\"?(password|oldpwd|newpwd|token|authorization|secret|idcard|identity|bank(card)?|mobile|phone|密码|手机号|身份证号)\\\"?\\s*[:=]\\s*)\\\"[^\\\"]*\\\"", "$1\\\"***\\\"");
|
}
|
}
|