springboot_log4j2_日志脱敏

时间:2025-03-23 07:08:36
@Plugin(name = "MaskSensitiveDataPolicy", category = Core.CATEGORY_NAME, elementType = "rewritePolicy", printObject = true) public class MaskSensitiveDataPolicy implements RewritePolicy { private static final Logger LOGGER = LoggerFactory.getLogger(MaskSensitiveDataPolicy.class); private String[] sensitiveClasses; private volatile boolean encryptEnable; //这里最好通过开关控制一下功能是否开和关 public static final Map<String, DesensitizedUtil.DesensitizedType> SENSITIVE_MAP = new HashMap<>(); static { //DesensitizedUtil 这里引用的是hutools SENSITIVE_MAP.put("username", DesensitizedUtil.DesensitizedType.CHINESE_NAME); SENSITIVE_MAP.put("password", DesensitizedUtil.DesensitizedType.PASSWORD); SENSITIVE_MAP.put("cellphone", DesensitizedUtil.DesensitizedType.MOBILE_PHONE); SENSITIVE_MAP.put("email", DesensitizedUtil.DesensitizedType.EMAIL); } @PluginFactory public static MaskSensitiveDataPolicy createPolicy( @PluginElement("sensitive") final String[] sensitiveClasses) { return new MaskSensitiveDataPolicy(sensitiveClasses); } private MaskSensitiveDataPolicy(String[] sensitiveClasses) { super(); encryptEnable = Boolean.parseBoolean(System.getProperty("")); this.sensitiveClasses = sensitiveClasses; } @Override public LogEvent rewrite(LogEvent event) { Message rewritten = rewriteIfSensitive(event.getMessage()); if (rewritten != event.getMessage()) { return new Log4jLogEvent.Builder(event).setMessage(rewritten).build(); } return event; } private Message rewriteIfSensitive(Message message) { // 确保已经通过设置系统属性`` 为 `false`关闭了garbage-free logging // 否则可能传入ReusableObjectMessage, ReusableParameterizedMessage或 // MutableLogEvent messages 导致不能重写。 // Make sure to switch off garbage-free logging // by setting system property `` to `false`. // Otherwise you may get ReusableObjectMessage, ReusableParameterizedMessage // or MutableLogEvent messages here which may not be rewritable... if (message instanceof ObjectMessage) { return rewriteObjectMessage((ObjectMessage) message); } if (message instanceof ParameterizedMessage) { return rewriteParameterizedMessage((ParameterizedMessage) message); } return message; } private Message rewriteObjectMessage(ObjectMessage message) { SensitiveStrategy sensitive = isSensitive(message.getParameter()); if (encryptEnable && sensitive.coincidence()) { return new ObjectMessage(sensitive.strategy(message.getParameter())); } return message; } private Message rewriteParameterizedMessage(ParameterizedMessage message) { Object[] params = message.getParameters(); boolean changed = rewriteSensitiveParameters(params); return changed && encryptEnable ? new ParameterizedMessage(message.getFormat(), params) : message; } private boolean rewriteSensitiveParameters(Object[] params) { boolean changed = false; for (int i = 0; i < params.length; i++) { SensitiveStrategy sensitive = isSensitive(params[i]); if (sensitive.coincidence()) { params[i] = sensitive.strategy(params[i]); changed = true; } } return changed; } private SensitiveStrategy isSensitive(Object parameter) { SensitiveStrategy defaultStrategy = new SensitiveStrategy() { @Override public boolean coincidence() { return false; } @Override public Object strategy(Object params) { return null; } }; if (null == parameter) return defaultStrategy; // TODo 加入缓存 LogEncryptClz logEncryptClz = parameter.getClass().getAnnotation(LogEncryptClz.class); boolean objInfer = null != logEncryptClz && logEncryptClz.enable() && parameter.getClass().getPackage().getName().startsWith("com.你的包名"); if (objInfer) { return new ObjectSensitiveStrategy(true); } if (parameter instanceof List) { return new ListSensitiveStrategy(true); } return defaultStrategy; } public interface SensitiveStrategy { boolean coincidence(); Object strategy(Object params); } public static class ObjectSensitiveStrategy implements SensitiveStrategy { private final boolean coincidence; public ObjectSensitiveStrategy(boolean coincidence) { this.coincidence = coincidence; } @Override public boolean coincidence() { return this.coincidence; } @Override public Object strategy(Object parameter) { if (null == parameter) { return null; } return objectStrategy(parameter); } public static Object objectStrategy(Object parameter) { JSONObject json = (JSONObject) JSONObject.toJSON(parameter); Map<String, Field> fileNameMaps = Stream.of(ReflectUtil.getFields(parameter.getClass())).filter(field -> { return field.isAnnotationPresent(LogEncryptFiled.class); }).collect(Collectors.toMap(Field::getName, Function.identity(), (a, b) -> b)); if (MapUtil.isEmpty(fileNameMaps)) { return parameter; } for (String key : json.keySet()) { Object v = json.get(key); if (null == v || !fileNameMaps.containsKey(key)) { continue; } Field field = fileNameMaps.get(key); LogEncryptFiled annotation = field.getAnnotation(LogEncryptFiled.class); DesensitizedUtil.DesensitizedType desensitizedType = annotation.type(); try { json.put(key, DesensitizedUtil.desensitized(String.valueOf(json.get(key)), desensitizedType)); } catch (Exception exception) { LOGGER.error("【数据脱敏】处理脱敏数据异常 源数据={}", json, exception); } } return JSONObject.toJSON(json); } } public static class ListSensitiveStrategy implements SensitiveStrategy { private final boolean coincidence; public ListSensitiveStrategy(boolean coincidence) { this.coincidence = coincidence; } @Override public boolean coincidence() { return this.coincidence; } @Override public Object strategy(Object parameter) { if (null == parameter) { return null; } List list = (List) parameter; if (CollUtil.isEmpty(list)) return null; List result = new ArrayList(); for (Object o : list) { LogEncryptClz annotation = o.getClass().getAnnotation(LogEncryptClz.class); if (null == annotation || !annotation.enable() || !o.getClass().getPackage().getName().startsWith("com.你的包名")) { continue; } if (o instanceof List) { result.add(strategy(o)); continue; } result.add(ObjectSensitiveStrategy.objectStrategy(o)); } return result; } } }