背景
项目做完,公司安全测试,说系统有安全漏洞,日志中未对用户信息进行脱敏处理,需要我对手机号进行脱敏处理,至少隐藏四位。锅从天上来,一期的项目的安全漏洞,之前没有安全测试,二期项目结束,测出来了,一脸懵的我~
好学和负责任的我(没办法,后来就算不算是二期项目的锅,我是系统Owner,最后还是算是系统问题),开始找资料怎么修复,网上一堆资料,怕个啥。
过程
项目使用的log4j-1.2.16.jar
浏览了很多网页的我,最后有些难受,脱敏的文章,基本上都是基于logback和log4j2的,关于log4j-1.2.16的,找到可用的文章参考总结为以下3种方法:
- 直接把要打印之前,把内容替换掉,这个可行,但是是个笨方法,要看每条有手机号的日志有哪些,然后去替换,难受呀,代码不美观,工作量多而且有可能会漏掉;
- 把 log4j-1.2.16换成 logback和log4j2,然后再脱敏,工作量同样不小,包名啥的也都不一样,身边的小伙伴建议我不要轻易动这一块,工作量太大,有可能会有大坑;
- 重写过滤器,我查了一些文章,没搞懂;
- 扩展PatternLayout类,具体怎么扩展,看了一下,不明白;
想扩展PatternLayout类,但又不知如何下手的我,后来就去看了log4j-1.2.16.jar的源码,就只修改log4j.properties和新增了一个ExPatternLayout.class(基本上是org.apache.log4j.PatternLayout类的代码,没改几行代码)
正则表达式只对连续11位数字且开头是1的进行处理,连续数字超过11位的不认为是手机号,不处理
代码
package com.xiaoxi.log;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.helpers.PatternConverter;
import org.apache.log4j.spi.LoggingEvent;
/**
* 扩展PatternLayout类
* 日志手机号码脱敏 第1位数字为1 连续 11位数字 第12位非数字 中间4位用*代替
*/
public class ExPatternLayout extends PatternLayout {
private static final String REGEX = "1(\\d{2})\\d{4}(\\d{4})(\\D)";
//$1,$2...是表示的小括号里的内容 $1是第一个小括号里的 ,$2是第2个小括号里的
//$1=(\\d{2}), $2=(\\d{4})
private static final String REPLACEMENT = "1$1****$2";
private StringBuffer sbuf = new StringBuffer(256);
private String pattern;
private PatternConverter head;
PatternLayout patternLayout;
public ExPatternLayout() {
this(DEFAULT_CONVERSION_PATTERN);
}
public ExPatternLayout(String pattern) {
this.pattern = pattern;
this.head = createPatternParser(pattern).parse();
}
@Override
public void setConversionPattern(String conversionPattern) {
this.pattern = conversionPattern;
this.head = createPatternParser(conversionPattern).parse();
}
@Override
public String getConversionPattern() {
return this.pattern;
}
@Override
public String format(LoggingEvent event) {
if (this.sbuf.capacity() > 1024)
this.sbuf = new StringBuffer(256);
else {
this.sbuf.setLength(0);
}
PatternConverter c = this.head;
while (c != null) {
c.format(this.sbuf, event);
c = c.next;
}
// 正则表达式替换之前返回值
return this.sbuf.toString().replaceAll(REGEX, REPLACEMENT);
}
}
原先 log4j.properties
log4j.rootLogger = stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold = INFO
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %p %c\:%L - %m%n
log4j.properties修改
# 把 log4j.appender.stdout.layout = org.apache.log4j.PatternLayout 修改为
log4j.appender.stdout.layout = com.xiaoxi.log.ExPatternLayout
log4j.rootLogger = stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.Threshold = INFO
log4j.appender.stdout.layout=com.xiaoxi.log.ExPatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %p %c\:%L - %m%n
测试代码
package com.xiaoxi.log;
import org.apache.log4j.Logger;
public class ExPatternLayoutTest {
private final static Logger log = Logger.getLogger(PatternLayoutDesensitization.class);
public static void main(String[] args) {
String phone1="\"phone\":\"15151822400\"";
log.info(phone1);
String phone2="\"phone\":\"151518224000\"";
log.info(phone2);
}
}
结果
2019-03-21 19:42:14.760 [main] INFO com.xiaoxi.log.ExPatternLayoutTest:10 - "phone":"151****2400"
2019-03-21 19:42:14.763 [main] INFO com.xiaoxi.log.ExPatternLayoutTest:13 - "phone":"151518224000"