首页 > 编程语言 >java打印日志时,如何对字段进行脱敏?

java打印日志时,如何对字段进行脱敏?

时间:2023-08-01 18:14:16浏览次数:51  
标签:对字段 java String formattedMessage value matcher return 脱敏

java打印日志时,如何对字段进行脱敏?
原文链接:https://blog.csdn.net/weixin_43901749/article/details/129150818
第一步,创建类继承MessageConverter,重写convert方法,添加注解 @Component("sensitive")
第二步,在logback.xml中增加 conversionRule 标签

在我们开发项目的时候,有些字段比较敏感,比如用户信息,这就需要在打印日志的时候对相关字段脱敏处理,本文提供的脱敏方案是使用conversionRule标签的方式,通过继承MessageConverter,在打印日志的时候对相关字段进行脱敏。
第一步,创建类继承MessageConverter,重写convert方法,如下:

public class SensitiveMessageConverter extends MessageConverter {
    /**
     * 正则匹配模式 
     */
    public static final Pattern REGEX_PATTERN = Pattern.compile("\\s*([\"]?[\\w]+[\"]?)(\\s*[:=]+[^\\u4e00-\\u9fa5@,.*{\\[\\w]*\\s*)([\\u4e00-\\u9fa5_\\-@.\\w]+)[\\W&&[^\\-@.]]?\\s*");
    @Override
    public String convert(ILoggingEvent event) {
        // 获取原始日志
        String formattedMessage = event.getFormattedMessage();
        return doConvert(formattedMessage);
    }
    private String doConvert(String formattedMessage) {
        if (StringUtils.isBlank(formattedMessage)) return formattedMessage;
        // 获取是否脱敏开关,可分环境配置是否开启
        Boolean convertSwitch = ApolloPropertyUtil.getBooleanProperty("log.sensitive.convert.switch", true);
        // 获取需要脱敏的字段。配置模板(key为脱敏模式,value为脱敏字段,可以有多个,other不脱敏):
        // {"name":["name","userName"],"mobilePhone":["phone"],"password":["password"],"idCard":["idcard"],"email":["email"],"other":["address"]}
        JSONObject jsonObject = ApolloPropertyUtil.getJSONObjectProperty("log.sensitive.convert.fields", "");
        // 是否开启脱敏开关
        if (!convertSwitch) return formattedMessage;
        if (Objects.isNull(jsonObject)) return formattedMessage;
        Matcher matcher = REGEX_PATTERN.matcher(formattedMessage);
        while (matcher.find()) {
            // 字段
            String key = matcher.group(1);
            key = key.replaceAll("\"", "");
            // 字段值
            String value = matcher.group(3);
            String mode = "";
            Iterator<String> iterator = jsonObject.keySet().iterator();
            while (iterator.hasNext()) {
                String next = iterator.next();
                List<String> list = (List<String>) jsonObject.get(next);
                if (list.contains(key)) {
                    // 命中当前属性属于哪一种脱敏模式(只能命中一种),目前支持 phone、password、idcard、other
                    mode = next;
                    break;
                }
            }
            // 没有命中脱敏模式,或者属性值为空,或者属性值为”null“,直接返回
            if (StringUtils.isAnyBlank(value, mode) || "null".equals(value)) continue;
            String afterValue = desensitize(mode, value);
            String origin = matcher.group(1) + matcher.group(2) + matcher.group(3);
            formattedMessage = formattedMessage.replace(origin, matcher.group(1) + matcher.group(2) + afterValue);
        }
        return formattedMessage;
    }
    /**
     * 脱敏
     *
     * @param mode 脱敏模式
     * @param value 脱敏的内容
     * @return 脱敏后的内容
     */
    private String desensitize(String mode, String value) {
        SensitiveModeEnum sensitiveModeEnum = SensitiveModeEnum.get(mode);
        // 获取不到相关脱敏模式,暂不支持,返回原日志
        if (Objects.isNull(sensitiveModeEnum)) return value;
        char[] chars = value.toCharArray();
        // 具体模式的策略可以再扩展(比如可以支持指定下标范围,指定正则,指定符号前面几位或者后面几位脱敏等等),这里暂不展开
        switch (sensitiveModeEnum) {
            case NAME:
                chars[0] = '*';
                break;
            case MOBILE_PHONE:
                for (int i = 3; i < 7; i++) {
                    chars[i] = '*';
                }
                break;
            case TELEPHONE:
                for (int i = 3; i < 5; i++) {
                    chars[i] = '*';
                }
                break;
            case ID_CARD:
                for (int i = 9; i < 13; i++) {
                    chars[i] = '*';
                }
                break;
            case PASSWORD:
                Arrays.fill(chars, '*');
                break;
            case EMAIL:
                for (int i = 3; i < 6; i++) {
                    chars[i] = '*';
                }
                break;
            case OTHER:
                break;
        }
        return new String(chars);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

第二步,在logback.xml中增加 conversionRule 标签

conversionWord是输入的日志信息,converterClass对应上面增加的类

<conversionRule conversionWord="msg" converterClass="xxx.xxx.log.SensitiveMessageConverter"/>
  • 1

测试

@Test
    public void test() {
        HashMap<Object, Object> map = new HashMap<>();
        Map<String, String> map1 = new HashMap<>();
        map1.put("email", "[email protected]");
        map1.put("address", "上海市详细地址");
        map.put("name", "张三分");
        map.put("sendPhone", "18912430987");
        map.put("password", "123456");
        map.put("detail", map1);
        log.info("结果:{}", JSON.toJSONString(map));
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

结果:

结果:{"password":"******","name":"*三分","sendPhone":"189****0987","detail":{"address":"上海市详细地址","email":"123***[email protected]"}} 
  • 1

标签:对字段,java,String,formattedMessage,value,matcher,return,脱敏
From: https://www.cnblogs.com/sunny3158/p/17598672.html

相关文章

  • java日志脱敏(密码/身份证/其他自定义等)logback
    java日志脱敏(密码/身份证/其他自定义等)logback原文链接:https://blog.csdn.net/weixin_39286166/article/details/126889660一.脱敏规则类 importch.qos.logback.classic.pattern.MessageConverter;importch.qos.logback.classic.spi.ILoggingEvent;importorg.apache.c......
  • java中使用异步方式调用接口@Async
    @Async使用:1、首先在启动类上开启注解@EnableAsync2、然后需要异步操作的方法上加上@Async*/publicclassAsyncTest{@Asyncpublicvoidtest()throwsInterruptedException{//做处理Thread.sleep(1000);}/**如果需要返回值的话,通过AsyncResult进行封装*/@AsyncpublicF......
  • javascript按钮通过cookie限制60s后才可以点击
    javascript按钮通过cookie限制60s后才可以点击1️⃣首先创建一个html页面,放入一个按钮 2️⃣设置点击按钮的触发函数一般当点击按钮都会有一些业务需要,在需求结束后,触发saveCookie的方法 3️⃣saveCookie方法当点击查询按钮之后,触发saveCooike方法,按钮倒计时需要一个结束......
  • JavaIO流
    JavaIO流基础概念数据流:一组有序,有起点和终点的字节的数据序列。包括输入流和输出流输入流:程序从输入流读取数据源。数据源包括外界(键盘、文件、网络…),即是将数据源读入到程序的通信通道输出流:程序向输出流写入数据。将程序中的数据输出到外界(显示器、打......
  • 使用Java进行串口通信
    引言 由于java的平台无关特性使得串口编程很困难。因为串口需要一个与特定平台实现的标准的API,而这对于java来说很困难。不幸的是,Sun在java的串口通信上没有太多关注。Sun已经定义了一个叫做JavaComm的串口通信API,但它的实现却不是javaSE(标准版)的一部分。Sun只为少数java平台提......
  • 每个Java开发者都应该知道的5个JDK工具
    JDK是Java语言的软件开发工具包,没有它就无法编译Java程序。目前,有许许多多的JDK工具呈现在大家面前,但最常用的莫过于java.exe、javac.exe、jar等。除了这几个,还有哪些呢?本文作者Joe拥有多年的Java开发经验,其在博客上分享了一篇文章:5JDKToolsEveryJavaDeveloperShouldKnow,笔......
  • 计算机基础与JavaScript初识
    一:编程介绍编程:就是让计算机为解决某个问题而使用某种程序设计语言编写程序代码,并最终得到结果的过程.计算机程序:就是计算机所执行的一系列的指令集合,而程序全部都是用我们所掌握的语言来编写的,所以人们要控制计算机一定要通过计算机语言向计算机发出命令。从事编程的人员,就是程......
  • java jsch sftp 中文乱码解决方案
    不同jsch版本对比--->JavaSSH/Sftp库——JSch/SSHJ方案一:maven版本:<dependency><groupId>com.jcraft</groupId><artifactId>jsch</artifactId><version>0.1.55</version></dependency>代码案例:packagecom.ch......
  • 从Java后端获取时间配置字符串,并在前端使用它来设置默认公布时间。
    <divclass="layui-inline"id="AItem"><labelclass="layui-form-labelsyn-form-item-require">公布时间:</label><divclass="layui-input-block">&......
  • 学习Java的第11天
    运算符算数运算符:+,-,*,/,%,++,--赋值运算符:=关系运算符:>,<,>=,<=,==,!=instanceof逻辑运算符:&&,||,!位运算符:&,|,^,~,>>,<<,>>>(了解!!!)条件运算符?:扩展赋值运算符:+=,-=,*=,/=packageoperator;publicclassDemo03{publicstaticv......