龙空技术网

Log4j2日志脱敏终极方案

靖宇迅 99

前言:

而今我们对“log4net配置脱敏”大约比较注意,同学们都需要学习一些“log4net配置脱敏”的相关内容。那么小编同时在网上网罗了一些有关“log4net配置脱敏””的相关资讯,希望兄弟们能喜欢,同学们快快来学习一下吧!

前言

相信大部分公司都会有对系统日志的格式和内容都有一定的要求和规范。其中内容部分,敏感信息(例如用户的身份证号,手机号,账号,邮箱等)的日志脱敏就是强诉求了。当然,目前针对日志脱敏的方案有很多,其中我见过最多的就是系统中自己定义一个LogUtils工具类做二次加工来实现。当时这并不是一个最好的解决方案,下面我会介绍一种针对日志脱敏,甚至日志其他处理的统一解决方案。

背景知识

在log4j中,有两个重要的概念,分别是Logger、Appender。Logger是负责具体的生产日志数据,我们平时的Logger.info(...)就是生产日志数据的过程。Appender则是负责将数据搬运到目的地,如console、文件、hive、网络设备等等。如下图(log4j日志框架的流程图)。

流程图

现状

目前出行普遍的日志脱敏方案是通过自定义一个LogUtils工具类,在LogUtils中定义了各个日志级别的打印方法,在方法中又做了一些二次加工的处理,比如:脱敏,格式化,traceId打印等。然后严格规定开发人员打印日志的时候必须要用到该类。(PS:这里只能人肉review,并没有idea的什么插件检查。其实即使有插件检查,也是最弱的系统化控制,逼不得已的做法。)这种方式,可能不仅你自己系统中在用,可能整个公司都在用,很多三方服务,也定义了一堆的LogUtils工具类。有时我在做类引入import的时候还得特别注意一下,自己是不是引入错了,毕竟大家对这个工具类的命名可选范围也不多,比如:LoggerUtils,LogUtil,LogUtils等,所以重名概率其实挺高的。

吓人的Log工具类(光是一个系统里面就有好几个自定义,还不包括外部三方的)

一个项目中的工具类

好吧,既然是一个普遍现象,那么这种方式存在哪些问题呢?

1,有感,不友好

○上面说的,开发人员需要时刻注意引入的LogUtils工具类是不是正确的,一不小心就出错了,而且review也很困难哦!!!○额外增加了一个LogUtils工具类,这个并没有统一标准,各系统之间做了很多重复工作,而且就因为没有标准,所以系统之间切换开发的时候,都得适应不同的入参写法,比如:A系统的info方法是三个入参,B系统就变成了4个了。○日志打印繁琐,目前普遍的LogUtils工具类都需要制定的传入一个Logger对象,这个对象就必须在每个需要打日志的地方通过Factory构造出来,每个类最上面都需要无脑的写上这么一行,而且也得注意import。无形增加了代码量。○由于有很多LogUtils,且还有lombok这种插件,总之打印方法,大家可能都有很多开发习惯。一不小心就会发现,之前的辛苦做的日志二次加工工作(比如:脱敏,格式化等)白做了。然而这个也是只能靠人肉review,review这块就增加了工作量。

2,业务有损,性能差

○三方污染,例如三方给你的jar包,里面也做了日志打印,他打印了一些敏感信息,就对你系统形成了污染。那么数据安全同事肯定找到你,然后你再去找他?然后他再给你升级?还要为此发布?是不是效率太低了。○由于LogUtils类的存在主要是为了做一些二次加工,而又一些加工可能会比较耗时的。那么用这种方式,势必会影响服务的RT。加入你的服务是个流程比较长的,且又打了很多日志,你是否知道你的日志额外耗时占用了多少呢?(ps:你根本享受不到异步日志给你带来的快速。)方案

上面说了挺多问题的,总之从技术人角度来看,人是最靠不住了,所以社会上才会有这么多渣男[看]。。。。诶,扯远了。

既然人靠不住,那么怎么避开人类这种危险的动物呢。首先想到的就是我们的log4j是不是提供了一些扩展能力(作为一款开源的中间件,如果开闭都没做的话,就太失败了。所以这里的答案是肯定的)。上面的背景知识上,可以看到,有两类节点提供了扩展点:Filter 和 LogEvent。

这两个扩展点,我就不做详细介绍了,因为不是本文要表达的重点。有兴趣大家可以自行度娘。

首先我们的要明确目标是什么,就是解决上面看到的痛点问题。找到了扩展点,至少解决了有感问题(底层日志框架是统一的);那么另一个问题就是,怎么实现日志异步的问题。可以参考Log4j2的异步化配置:

1,添加依赖:

<dependency>

<groupId>com.lmax</groupId>

<artifactId>disruptor</artifactId>

<version>3.4.4</version>

</dependency>

2,配置xml

<AsyncLogger name="Log4j2Test" level="WARN" includeLocation="false" additivity="false">

<AppenderRef ref="Console"/>

</AsyncLogger>

异步日志配置好后。那么我们就可以搭这个顺风车了。如下图,有两个实现日志异步的点,AsyncLogger和AsyncAppender。

●异步Logger通过使用LMAX Disruptor环形队列和单独的处理线程,避免了锁的竞争,从而实现更高的吞吐量。队列大小默认4096。

●异步Appender则是使用了java中的ArrayBlockingQueue,默认队列大小1024。

AsyncAppender相对AsyncLogger来说,是一种比较老的异步方式,且官方实测的结论也是AsyncLogger性能大于AsyncAppender。所以普遍方式都是采用AsyncLogger。例如大家上次改造的时候也是。

结合以上,我们的方案,就是通过LogEvent去做切入。

方案确定了,那么就干吧。

第一步:实现log4j2的RewritePolicy接口,重写logEvent

第二步:在log4j2-spring.xml中引入插件。插件类:(这里只是示例仅供参考,因为脱敏部分是通过自研正则实现,后续会改用脱敏sdk。所以切不可copy,出现问题概不负责。后续优化后,会更新)

标签: #log4net配置脱敏 #python的logging模块对日志做脱敏处理