咱们常见的日志主要有两种:一种是路由层日志,一种是应用日志。

生产日志敏感信息处理实践_java

路由层日志

路由层日志因为主要作用是监控某一个地址有没有正确被转发到对应应用,以及通过状态码来监控应用有没有正确被处理。所以日志也主要包含这两个内容:请求路径+状态码。遇到由于配置日志的信息打印过多:打印了请求路径+请求参数,因为参数中存在敏感信息,造成风险。

咱们使用k8s的ingress来实现域名访问时,ingress本质还是nginx+lua那一套,所以都是可以进行配置的。可以配置打印:请求路径、请求参数、请求内容长度、状态码、返回响应等。

应用日志

应用日志的请求以及响应对排查问题非常关键。在调用第三方系统时一个比较好的实践是try finally并在finally模块里添加请求响应的关键信息。这时候如果日志中出现了敏感信息怎么办呢?

业界普遍的做法是正则表达式过滤。但是正则表达式效率是个大问题。我试过在同步日志的情况下,全链路配置了脱敏正则表达式,本来600ms左右响应的接口要10s以上甚至直接超时了。这个数据看起来有些夸张,有可能是有些接口性能下来之后,调用方配置了超时重试,导致整体的延迟。

这个问题可能在某些已经规范化了的项目中不会出现。因为配置了异步日志的化,理论上就不占用业务处理时间。我做了测试。

以下是处理脱敏的代码

public class MaskingPatternLayoutEncoder extends PatternLayoutEncoder {


    /**
     * 使用自定义 MyLogbackPatternLayout 格式化输出
     */
    @Override
    public void start() {
        CustomPatternLayout patternLayout = new CustomPatternLayout();
        patternLayout.setContext(context);
        patternLayout.setPattern(this.getPattern());
        patternLayout.setOutputPatternAsHeader(outputPatternAsHeader);
        patternLayout.start();
        this.layout = patternLayout;
        started = true;
    }
}
public class CustomPatternLayout extends PatternLayout {
    Pattern pattern = Pattern.compile("(mobile:\\d+)|(bankCode:\\d+)|email:\\S+@");


    /**
     * 格式化日志信息
     *
     * @param event ILoggingEvent
     * @return 日志信息
     */
    @Override
    public String doLayout(ILoggingEvent event) {
        // 占位符填充
        String msg = super.doLayout(event);
        // 脱敏处理
        return this.buildSensitiveMsg(msg);
    }


    /**
     * 根据配置对日志进行脱敏
     *
     * @param msg 消息
     * @return 脱敏后的日志信息
     */
    public String buildSensitiveMsg(String msg) {
        return pattern.matcher(msg).replaceAll("****");
    }
}

在配置文件里配置使用脱敏

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="com.gzhu.funai.filter.MaskingPatternLayoutEncoder">
            <Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
            <!-- 设置字符集 -->
            <charset>UTF-8</charset>
        </encoder>
    </appender>

测试代码

for(inti=0; i<10000; i++) {
    log.info("mobile:13121568938, email:xiedfdfd@126.com, bankCode:6226090106001010");
}

同步日志完成平均5s。异步稳定时1s多。随着正则表达式匹配规则的增加,同步日志完成时间有明显增加,异步日志完成时间没有明显增加。

同步日志改异步,短短几行代码,全链路估计能省出来不少服务器。

<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
        <!-- 不丢失日志的话,默认的队列长度是256 -->
        <queueSize>256</queueSize>
        <!-- 添加内部appender,如Console或File -->
        <appender-ref ref="CONSOLE"/>
    </appender>