java 日志脱敏

环境搭建

搭建基础的spring boot工程,引入logback-spring.xml基础础配置文件

基本实现方式

修改配置

在logback-spring文件的基础上添加脱敏开关,启动监听器,及日志转换器

<!--是否脱敏配置-->
<if condition='"false".equals(property("SENSITIV_FLAG"))'>
    <then>
      <!-- 关闭日志脱敏 -->
      <property scope="context" name="converterCanRun" value="false"/>
    </then>
   <else>
    <!-- 开启日志脱敏 -->
      <property scope="context" name="converterCanRun" value="true"/>
    </else>
</if>
<!--启动监听器-->
<contextListener class="com.person.share.log.LoggerStartupListener"/>
<!--日志转换器-脱敏-->
<conversionRule conversionWord="msg" converterClass="com.person.share.log.SensitiveConverter"> </conversionRule>

实现描述

LoggerStartupListener的定义如下:
用于初始化加载需要进行敏感字段处理的ContextListener,根据context对应的property加载自定义的需要的字段

public class LoggerStartupListener extends ContextAwareBase implements LoggerContextListener, LifeCycle {
    
    private boolean started = false;

    public void start() {
        if (!this.started) {
                this.prepareSensitiveDataKeyList();//加载自定义的脱敏字段,如添加一个手机号的字段列表
                this.started = true;
        }
    }
    private void prepareSensitiveDataKeyList() {
        String allowRun = this.context.getProperty("converterCanRun");
        if ("true".equals(allowRun)) {
            List<String> phoneList = SensitiveConverter.phoneList;
            String extPhoneList = this.context.getProperty("SENSITIVE_PHONE");
            if (StringUtils.isNotBlank(extPhoneList)) {
                phoneList.addAll(Arrays.asList(extPhoneList.split(",")));
            }
            SensitiveConverter.phoneList = phoneList;
            if (CollectionUtils.isNotEmpty(SensitiveConverter.sensitiveDataKeyList)) {
                return;
            }
            SensitiveConverter.sensitiveDataKeyList.addAll(SensitiveConverter.ignoreList);
            SensitiveConverter.sensitiveDataKeyList.addAll(SensitiveConverter.phoneList);
        }
    }
    public boolean isStarted() {
        return this.started;
    }
}

SensitiveConverter的定义如下:
脱敏规则的实现,如下是对通过phoneNo记录手机号的json字符串进行md5处理的一种可能方式

public class SensitiveConverter extends MessageConverter {

    private String converterCanRun;
    public static List<String> ignoreList = Lists.newArrayList();
    /**
     * 包含电话号码的字段过滤
     */
    public static  List<String> phoneList = Arrays.asList("phoneNo","phone");

    public static List<String> sensitiveDataKeyList = Lists.newArrayList();
    @Override
    public String convert(ILoggingEvent event) {
        Context context = getContext();
        String allowRun = context.getProperty("converterCanRun");
        setConverterCanRun(StringUtils.defaultIfBlank(allowRun,"true"));//默认进行脱敏
        String originMsg =  event.getFormattedMessage();
        originMsg = sensitiveInvoke(originMsg);
        return originMsg;
    }
    private String sensitiveInvoke(String originMsg) {//originMsg的格式形如{"phoneNo":"12345678900"}
       String tempMsg = originMsg;
        if ("true".equals(this.converterCanRun)) {
            try {
                if (sensitiveDataKeyList.size() > 0) {
                    Iterator var3 = sensitiveDataKeyList.iterator();

                    while(var3.hasNext()) {
                        String key = (String)var3.next();
                        int index = -1;

                        while(true) {
                            index = tempMsg.indexOf(key, index + 1);
                            if (index != -1 ) {
                                int valueStart = this.getValueStartIndex(tempMsg, index + key.length());
                                int valueEnd = this.getValueEndEIndex(tempMsg, valueStart);
                                String subStr = tempMsg.substring(valueStart, valueEnd);
                                subStr = mask(subStr, key);
                                tempMsg = tempMsg.substring(0, valueStart) + subStr + tempMsg.substring(valueEnd);
                            }
                            if (index == -1) {
                                break;
                            }
                        }
                    }
                }
            } catch (Exception var9) {
               
            }
        }
        return tempMsg;
    }
   private int getValueStartIndex(String msg, int valueStart) {
        while(valueStart < msg.length()) {
            char ch = msg.charAt(valueStart);
            if (ch == ':') {
                ++valueStart;
                ch = msg.charAt(valueStart);
                if (ch == '"') {
                    ++valueStart;
                }
                return valueStart;
            }
            ++valueStart;
        }
        return valueStart;
    }
    private int getValueEndEIndex(String msg, int valueEnd) {
        while(true) {
            if (valueEnd != msg.length()) {
                char ch = msg.charAt(valueEnd);
                if (ch == '"') {
                    if (valueEnd + 1 != msg.length()) {
                        char nextCh = msg.charAt(valueEnd + 1);
                        if ( nextCh != ',' && nextCh !='}') {
                            ++valueEnd;
                            continue;
                        }

                        while(valueEnd > 0) {
                            char preCh = msg.charAt(valueEnd - 1);
                            if (preCh != '\\') {
                                break;
                            }
                            --valueEnd;
                        }
                    }
                } else if ( ch != ',' && ch != '}' ) {
                    ++valueEnd;
                    continue;
                }
            }
            return valueEnd;
        }
    }
    private String mask(String subMsg, String key) {
        if (ignoreList.contains(key)) {
            return "*IGNORE*";
        } else if (phoneList.contains(key)) {
            return "'" + MD5Util.MD5(subMsg) + "'";
        }else {
            return subMsg;
        }
    }
    public void setConverterCanRun(String allowRun){
        this.converterCanRun = allowRun;
    }
}

MD5Util是md5的一个工具类实现

实现效果

如上启动对应的应用后,当使用日志log.info or其他方式记录日志时,原文为{“phoneNo”:“12345678900”}在日志文件中可能被记录为*{“phoneNo”:“‘dhfidhgidae3hgd8dgd’”}*这样的md5的概要描述。如果需要在控制台上也要以密文输出的话,可以脱敏配置之后添加ConsoleAppender,类似下面的配置

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>
                %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger -  %X{url}?%X{queryString} code:%X{businessResult} - %msg%n
            </pattern>
            <charset>UTF-8</charset>
        </encoder>
</appender>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值