slf4j如何脱敏日志敏感信息

如何脱敏日志敏感信息

代码处理

package com.carbonstop.webank.config;

import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.apache.commons.lang3.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @className: SensitiveFilterPatternLayout
 * @author: szx
 * @date: 2022-11-10 09:50
 * @description:
 */
public class SensitiveFilterPatternLayout extends MessageConverter {
    /**
     * 日志脱敏开关
     */
    private static String converterCanRun = "true";
    /**
     * 日志脱敏关键字
     */
    private static String sensitiveDataKeys = "email,username,mobile,realName,chineseName,englishName," +
            "loginticket,idcard,idCard,address,regAddress,produceAddress,updateByName,updateName,createByName,createName";

    private static Pattern pattern = Pattern.compile("[0-9a-zA-Z]");

    @Override
    public String convert(ILoggingEvent event){
        // 获取原始日志
        String oriLogMsg = event.getFormattedMessage();

        // 获取脱敏后的日志
        String afterLogMsg = invokeMsg(oriLogMsg);
        return afterLogMsg;
    }


    /**
     * 处理日志字符串,返回脱敏后的字符串
     * @return
     */
    public String invokeMsg(final String oriMsg){
        String tempMsg = oriMsg;
        if("true".equals(converterCanRun)){
            // 处理字符串
            if(sensitiveDataKeys != null && sensitiveDataKeys.length() > 0){
                String[] keysArray = sensitiveDataKeys.split(",");
                for(String key: keysArray){
                    int index= -1;
                    do{
                        index = tempMsg.indexOf(key, index+1);
                        if(index != -1){
                            // 判断key是否为单词字符
                            if(isWordChar(tempMsg, key, index)){
                                continue;
                            }
                            // 寻找值的开始位置
                            int valueStart = getValueStartIndex(tempMsg, index + key.length());

                            // 查找值的结束位置(逗号,分号)........................
                            int valueEnd = getValuEndEIndex(tempMsg, valueStart);

                            // 对获取的值进行脱敏
                            String subStr = tempMsg.substring(valueStart, valueEnd);
                            subStr = tuomin(subStr, key);
                            ///
                            tempMsg = tempMsg.substring(0,valueStart) + subStr + tempMsg.substring(valueEnd);
                        }
                    }while(index != -1);
                }
            }
        }
        return tempMsg;
    }

    private String tuomin(String submsg, String key){
        // idcard:身份证号, realname:姓名, bankcard:银行卡号, mobile:手机号
        if(!StringUtils.isEmpty(submsg)){
            return submsg.substring(0,1)+"******";
        }else{
            return "******";
        }

    }


    /**
     * 判断从字符串msg获取的key值是否为单词 , index为key在msg中的索引值
     * @return
     */
    private boolean isWordChar(String msg, String key, int index){

        // 必须确定key是一个单词............................
        if(index != 0){ // 判断key前面一个字符
            char preCh = msg.charAt(index-1);
            Matcher match = pattern.matcher(preCh + "");
            if(match.matches()){
                return true;
            }
        }
        // 判断key后面一个字符
        char nextCh = msg.charAt(index + key.length());
        Matcher match = pattern.matcher(nextCh + "");
        if(match.matches()){
            return true;
        }
        return false;
    }

    /**
     * 获取value值的开始位置
     * @param msg 要查找的字符串
     * @param valueStart 查找的开始位置
     * @return
     */
    private int getValueStartIndex(String msg, int valueStart ){
        // 寻找值的开始位置.................................
        do{
            char ch = msg.charAt(valueStart);
            if(ch == ':' || ch == '='){ // key与 value的分隔符
                valueStart ++;
                ch = msg.charAt(valueStart);
                if(ch == '"'){
                    valueStart ++;
                }
                break;    // 找到值的开始位置
            }else{
                valueStart ++;
            }
        }while(true);
        return valueStart;
    }

    /**
     * 获取value值的结束位置
     * @return
     */
    private int getValuEndEIndex(String msg,int valueEnd){
        do{
            if(valueEnd == msg.length()){
                break;
            }
            char ch = msg.charAt(valueEnd);

            if(ch == '"'){ // 引号时,判断下一个值是结束,分号还是逗号决定是否为值的结束
                if(valueEnd+1 == msg.length()){
                    break;
                }
                char nextCh = msg.charAt(valueEnd+1);
                if(nextCh ==';' || nextCh == ','){
                    // 去掉前面的 \  处理这种形式的数据
                    while(valueEnd>0 ){
                        char preCh = msg.charAt(valueEnd-1);
                        if(preCh != '\\'){
                            break;
                        }
                        valueEnd--;
                    }
                    break;
                }else{
                    valueEnd ++;
                }
            }else if (ch ==';' || ch == ',' || ch == '}'){
                break;
            }else{
                valueEnd ++;
            }

        }while(true);
        return valueEnd;
    }

}

logback.xml中的配置

<conversionRule conversionWord="msg" converterClass="com.carbonstop.webank.config.SensitiveFilterPatternLayout"/>

在这里插入图片描述

  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要在项目中添加 slf4j 的依赖,例如: ```xml <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.30</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> ``` 然后,在代码中使用 slf4j 进行日志输出。例如: ```java import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class MyClass { private static final Logger logger = LoggerFactory.getLogger(MyClass.class); public void myMethod() { logger.info("This is a log message."); } } ``` 这里我们使用了 `LoggerFactory.getLogger()` 方法获取一个 Logger 对象,然后使用 `logger.info()` 方法输出日志。在这个例子中,我们使用了 `info` 级别的日志,还可以使用 `debug`、`warn`、`error` 等级别,具体使用哪个级别需要根据实际情况来定。 最后,我们需要配置 logback.xml 文件来指定日志输出的方式和目标文件。例如: ```xml <configuration> <appender name="FILE" class="ch.qos.logback.core.FileAppender"> <file>/var/log/myapp.log</file> <append>true</append> <encoder> <pattern>%d{ISO8601} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender> <root level="INFO"> <appender-ref ref="FILE" /> </root> </configuration> ``` 上述配置中,我们将日志输出到 `/var/log/myapp.log` 文件中,使用 `ISO8601` 格式的时间戳,包含线程信息日志级别等。具体的配置方式需要根据实际需求来定。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值