业务场景
开发中,对于打印出来的日志文件,涉及到敏感信息,类似银行卡,姓名,身份证等等,通常会根据需求进行关键词的隐藏,比如姓名:万旭会处理后在日志中显示:姓名:万*。这样的过程叫做日志关键词脱敏。
如下使用logback进行脱敏操作和配置。
配置枚举类
用来管理需要脱敏的关键词
public enum KeywordTypeEnum {
/**
* 真实姓名
*/
TRUE_NAME("trueName","真实姓名"),
/**
* 身份证号码
*/
ID_CARD_NO("idCardNo","身份证号码"),
/**
* 银行卡号
*/
BANKCARD_NO("bankcardNo","银行卡号"),
/**
* 手机号码
*/
PHONE_NO("phoneNo","手机号码"),
/**
* 其它
*/
OTHER("other","其它");
private String keywordType;
private String desc;
KeywordTypeEnum(String keywordType, String desc) {
this.keywordType = keywordType;
this.desc = desc;
}
/**
* 通过keyword获取对象
*/
public static KeywordTypeEnum getMessageType(String keywordType) {
for (KeywordTypeEnum c : KeywordTypeEnum.values()) {
if (c.getKeywordType().equals(keywordType)) {
return c;
}
}
return null;
}
public String getKeywordType() {
return keywordType;
}
public String getDesc() {
return desc;
}
}
全局编解码配置文件
主要关联logback配置进行属性值的读取
public class CommonPatternLayoutEncoder extends PatternLayoutEncoder {
protected static final String PATTERN_D1 = "%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread]";
protected static final String PATTERN_D2 = " [{0}:%X'{'{1}'}']";
protected static final String PATTERN_D3_S1 = " [%level] %logger{10}-%L ";
//0:日志脱敏开关,1:查找深度(超过深度后停止正则匹配),2:日志最大长度,3:待脱敏关键字
protected static final String PATTERN_D3_S2 = "%msg'{'{0},{1},{2},{3}'}'%n";
//日志脱敏开关
protected String converterCanRun = "true";
//待脱敏关键字
protected String sensitiveData;
//自定义MDC的key,多个key用逗号分隔。
protected String mdcKeys;
//匹配深度(若深度值过大影响性能)
protected int depth = 12;
//单条消息的最大长度
protected int maxLength = 2048;
@Override
public void start() {
if (getPattern() == null) {
StringBuilder sb = new StringBuilder();
sb.append(PATTERN_D1);
//拼接MDC参数
if (mdcKeys != null) {
String[] keys = mdcKeys.split(",");
for (String key : keys) {
sb.append(MessageFormat.format(PATTERN_D2, key, key));
}
}
sb.append(PATTERN_D3_S1);
if (maxLength < 0 || maxLength > 10240) {
maxLength = 2048;
}
sb.append(MessageFormat.format(PATTERN_D3_S2, converterCanRun,String.valueOf(depth),String.valueOf(maxLength),sensitiveData));
setPattern(sb.toString());
}
super.start();
}
public String getSensitiveData() {
return sensitiveData;
}
public void setSensitiveData(String sensitiveData) {
this.sensitiveData = sensitiveData;
}
public String getConverterCanRun() {
return converterCanRun;
}
public void setConverterCanRun(String converterCanRun) {
this.converterCanRun = converterCanRun;
}
public String getMdcKeys() {
return mdcKeys;
}
public void setMdcKeys(String mdcKeys) {
this.mdcKeys = mdcKeys;
}
public int getMaxLength() {
return maxLength;
}
public void setMaxLength(int maxLength) {
this.maxLength = maxLength;
}
public int getDepth() {
return depth;
}
public void setDepth(int depth) {
this.depth = depth;
}
@Override
public String getPattern() {
return super.getPattern();
}
@Override
public void setPattern(String pattern) {
super.setPattern(pattern);
}
自定义转换器
主要是对日志进行个性化匹配以及业务处理
public abstract class BaseConverter extends MessageConverter {
// 日志脱敏开关
protected String converterCanRun = "true";
// 匹配深度
protected Integer depth = 12;
//单条消息的最大长度,主要是message
protected Integer maxLength = 2048;
// 日志脱敏关键字
protected static Map<String,String> keywordMap = new HashMap<>();
@Override
public void start