使用log4j2对日志脱敏

时间:2025-03-22 22:24:37
package com.rick.log4j.factory.event; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.Marker; import org.apache.logging.log4j.core.LogEvent; import org.apache.logging.log4j.core.config.Property; import org.apache.logging.log4j.core.impl.Log4jLogEvent; import org.apache.logging.log4j.core.impl.LogEventFactory; import org.apache.logging.log4j.message.Message; import org.apache.logging.log4j.message.SimpleMessage; import java.util.List; import java.util.Objects; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author rick * E-mail:sophie_zelmani@ * @version 2021/8/26 10:51 */ public class CustomLogEventFactory implements LogEventFactory { //public class CustomLogEventFactory extends ReusableLogEventFactory { private static final CustomLogEventFactory instance = new CustomLogEventFactory(); /** * <p> * mask RegExp, to reserve the first three * and last four chars for search use. * </p> */ private static final String MASK_REGEX = "(?<=.{3}).(?=.*....)"; /** * Credit Card Type Prefix Length * American Express 34, or 37 15 * MasterCard 51 through 55 16 * Visa 4 13 or 16 * Diners Club and Carte Blanche 36,38,or 300 through 305 14 * Discover 6011 16 * JCB 2123 or 1800 15 * JCB 3 16 */ private Pattern creditCardPattern = Pattern.compile("((?:(?:4\\d{3})|(?:5[1-5]\\d{2})|6(?:011|5[0-9]{2}))(?:-?|\\040?)(?:\\d{4}(?:-?|\\040?)){3}|(?:3[4,7]\\d{2})(?:-?|\\040?)\\d{6}(?:-?|\\040?)\\d{5})"); /** * @return */ @SuppressWarnings("unused") public static CustomLogEventFactory getInstance() { return instance; } /** * Creates a log event. * * @param loggerName The name of the Logger. * @param marker An optional Marker. * @param fqcn The fully qualified class name of the caller. * @param level The event Level. * @param message The Message. * @param properties Properties to be added to the log event. * @param throwable An optional Throwable. * @return The LogEvent. */ public LogEvent createEvent(String loggerName, Marker marker, String fqcn, Level level, Message message, List<Property> properties, Throwable throwable) { String formattedMessage = message.getFormattedMessage(); String obfuscatedMsg = obfuscateIfNecessary(creditCardPattern, formattedMessage); Message handledMsg = new SimpleMessage(obfuscatedMsg); return new Log4jLogEvent(loggerName, marker, fqcn, level, handledMsg, properties, throwable); } /** * <p> * obfuscate the digital chars * which exist in the given string with '*' character * except the first 4 chars ahead and last 4 chars behind. * </p> * * examples: * 4111-2222-3333-4444 -> 4111-****-****-4444 * 4111222233334444 -> 4111********4444 * 4111 2222 3333 4444 -> 4111********4444 * * @param sensitiveData * @return obfuscated string */ @SuppressWarnings("unused") private String obfuscate(String sensitiveData) { char[] chars = sensitiveData.toCharArray(); int prefixLength = 4;// reserve first four chars int suffixLength = 4;// reserve last four chars if ((chars.length <= prefixLength + suffixLength)) { return sensitiveData; } for (int i = prefixLength; i < chars.length - suffixLength; i++) { if (isDigital(chars[i])) { chars[i] = '*'; } } return new String(chars); } /** * obfuscate the digital chars which exist in the given string * with '*' character except the first three * chars ahead and last four chars behind. * eg. * 4111-2222-3333-4444 -> 411************4444 * 4111222233334444 -> 411*********4444 * 4111 2222 3333 4444 -> 411************4444 * * @param sensitiveData * @return obfuscated string */ private String obfuscateByRegex(String sensitiveData) { return sensitiveData.replaceAll(MASK_REGEX, "*"); } /** * @param ch * @return whether the given char is numeric */ private boolean isDigital(char ch) { return (ch >= 48 && ch <= 57); } /** * @param formattedMsg #{@link Message#getFormattedMessage()} * @return obfuscated string. */ private String obfuscateIfNecessary(Pattern pattern, String formattedMsg) { Matcher matcher = pattern.matcher(formattedMsg); StringBuffer sb = new StringBuffer(); while (matcher.find()) { String original = matcher.group(); if (!Objects.isNull(original)) { // String obfuscated = obfuscate(original); String obfuscated = obfuscateByRegex(original); matcher.appendReplacement(sb, obfuscated); } } if (sb.length() != 0) { matcher.appendTail(sb); return sb.toString(); } return formattedMsg; } }