【日志脱敏】Springboot集成日志框架脱敏实战

2023-11-03

针对日志打印而不能泄露用户隐私需求,需要利用相应日志框架实现脱敏,本文基于log4j/logback,重写相应方法,匹配出正则并转换为脱敏后的日志。效果展示如下
{“name”:“李**”, “idNumber”:“110106********226X”,“mobile”:“130****2333”}

1.基于log4j/logback,重写log4j的MessageConverter类

import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class xxxLogConverter extends MessageConverter{
	@Override
	public String convert(ILoggeringEvent event){
		String sourceLog = event.getFormattedMessage();
		return logSecurity(sourceLog);
	}
	
	public String logSecurity(final String sourceLog){
		return HideStrUtil.loghandle(sourceLog);
	}

2.加入屏蔽逻辑

import org.apache.commons.lang3.StringUtils;

import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class HideStrUtil {

    public static final String regexPhone = "1[3456789]\\d{9}";
    public static final String regexCard  = "([1-9]\\d{5}[1-9]\\d{3}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx])|([1-9]\\d{5}\\d{2}((0[1-9])|10|11|12)(([0-2][1-9])|10|20|30|31)\\d{3})";
    // public static final String regexName  = "[\u4e00-\u9fa5]{2,20}";
    public static final String regexName  = "(\\\"name\\\":\\\"|\\\"cust_name\\\":\\\"|\\\"NAME\\\":\\\"|\\\"CUST_NAME\\\":\\\"|name=|cust_name=|name:\\\"|cust_name:\\\")[\u4e00-\u9fa5]{2,20}";

    public static final Pattern pattern = Pattern.compile("[0-9a-zA-Z]");
    /**
     * 整合手机号、身份证号和姓名的脱敏
     * @param str
     * @return
     */
    public static String logHandle(String str) {

        if (StringUtils.isNotBlank(str)) {
            str = matchRegexAndHide(regexCard, str);
            str = matchRegexAndHide(regexPhone, str);
            str = matchRegexAndHide(regexName, str);
        }
        return str;
    }

    /**
     * 隐藏身份证里的出生日期,隐藏手机号中间4位,隐藏姓名里除最后一位的其他信息
     * @param str
     * @return
     */
    public static String hideMidStr(String str,String regex) {
        String str2 = str;
        if (StringUtils.isNotBlank(str)) {
            if (str.length() == 18 && regexCard.equals(regex)) {
                if (str.endsWith("X") || str.endsWith("x")){
                    StringBuilder s = new StringBuilder(str);
                    str2 = s.replace(6, 14, "********").toString();
                    return str2;
                }
                str2 = str.replaceAll("(\\d{6})\\d{8}(\\d{4})", "$1********$2");
            } else if (str.length() == 11 && regexPhone.equals(regex)) {
                str2 = str.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");
            } else if(regexName.equals(regex) && str.indexOf(":")!=-1){
                String[] param = str.split(":");
                if(param!=null && param.length==2){
                    String name = String.valueOf(param[1].charAt(1));
                    str2 = param[0] +":\""+StringUtils.rightPad(name, StringUtils.length(param[1])-1, "*");
                }
            }else{
                String[] param = str.split("=");
                if(param!=null && param.length==2){
                    String name = String.valueOf(param[1].charAt(0));
                    str2 = param[0] +"="+StringUtils.rightPad(name, StringUtils.length(param[1]), "*");
                }
            }
        }
        return str2;
    }

    /**
     * 根据传入的正则进行匹配,并脱敏,返回脱敏结果
     * @param regex
     * @param str
     * @return
     */
    public static String matchRegexAndHide(String regex, String str) {

        StringBuffer sb = new StringBuffer();

        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        while (matcher.find()){
            String group = matcher.group();
            if (!isNumOrLetter(str,group)){
                matcher.appendReplacement(sb,hideMidStr(group,regex));
            }
        }
        matcher.appendTail(sb);

        return sb.toString();
    }


    /**
     * 获取匹配到关键词的前一个和后一个字符是否为数字或字母
     * @return
     */
    public static boolean isNumOrLetter(String msg, String key){
        int index = msg.indexOf(key);
        // System.out.println(index);
        if (index != -1){
            // 判断key前面一个字符
            if(index != 0){
                char preCh = msg.charAt(index-1);
                // System.out.println(preCh);
                Matcher match = pattern.matcher(preCh + "");
                if(match.matches()){
                    return true;
                }
            }
            // 判断key后面一个字符
            char nextCh = msg.charAt(index + key.length());
            // System.out.println(nextCh);
            Matcher match = pattern.matcher(nextCh + "");
            if(match.matches()){
                return true;
            }
        }
        return false;
    }





    public static void main(String[] args) {
        String str1 = "{\"reason\":\"成功 \",\"result\":{\"jobid\":\"JH2131171027170837443588J6\",\"realname\":\"林有有\"," +
                "\"bankcard\":\"6666430106138888\",\"idcard\":\"130333198901196666\",\"mobile\":\"13288886666\",\"res\":\"1\",\"message\":\"验证成功\"}," +
                "\"error_code\":0}";

        String str2 = "{\"appkey\":\"E25158BA10104C9180D47FD20CA024B9\",\"idcard\":\"330103197607086666\",\"realname\":\"李有有\",\n" +
                "\"applyPhone\":\"18577776667\",\"inviteCode\":\"353753\",\"signature\":\"M2U3Y2M0OTgyZmM1NmUzODAyNjQ0YjNiNGViODBlNTI=\",\n" +
                "\"timestamp\":\"1592544985\"}";

        boolean b = isNumOrLetter(str1, "130333198901196666");
        System.out.println(b);
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【日志脱敏】Springboot集成日志框架脱敏实战 的相关文章

随机推荐

  • Socket 关于设置Socket连接超时时间

    做网络编程的人对setSoTimeout方法一定很熟悉 都知道是设置连接的超时时间 但是我在网上找资料时发现很多人把这个超时时间理解成了链路的超时时间 我看了一下JDK 关于这个方法的说明 其实根本不是链路的超时时间 Java代码 setS
  • Android ImageView使用详解(系列教程三)

    目录 一 ImageView简介 二 ImageView基本使用 三 ImageView常用属性 四 几种图片的加载方法 五 ImageView的缩放类型 一 ImageView简介 ImageView是Android开发中最常用的组件之一
  • 华为OD机试 Python 报数问题

    描述 你和你的朋友们围成一个圈玩游戏 从第一个人开始 依次报数 1 2 3 当数到3的时候 那个人就得退出游戏 然后从他的下一个朋友继续开始 1 2 3 同样的 数到3的人又得退出 这样一直进行下去 直到圈里只剩下一个人 人会是谁 任务 给
  • 华为OD机试真题 Java 实现【Linux 发行版的数量】【2023Q1 100分】

    目录 一 题目描述 二 输入描述 三 输出描述 四 解题思路 五 Java算法源码 六 效果展示 1 输入 2 输出 3 说明 一 题目描述 Linux 操作系统有多个发行版 distrowatch com 提供了各个发行版的资料 这些发行
  • 集合转换为Jsoin存入redis

    重温复习redis 要将对象集合存入redis作为缓存 上网找了个json串转集合的工具类 这里记录一下 import java io IOException import java util ArrayList import java u
  • js获取input上传文件的文件名和扩展名的方法

  • WLAN配置

    SW1 sysname SW1 修改名称 undo info center enable 关闭提示 vlan batch 100 to 102 批量创建vlan 100 101 102 interface GigabitEthernet0
  • Ethereum geth 同步区块的三种模式

    Ethereum 以太坊 当前交易多 截止当前 2018 02 04 已经有5029238个区块 区块大小在150G左右 如果全部同步 并且严格逐个验证 需要太多的时间和计算 作者曾经用一台实体机 8核 16GB内存 2TB机械硬盘的del
  • leetcode1921.消灭怪物的最大数量(中等)

    解法 排序 贪心 具体 计算出每个怪物到达城市的时间 然后排序 class Solution public int eliminateMaximum vector
  • 深度学习论文笔记(可解释性)——CAM与Grad-CAM

    文章目录 主要工作 Global Average Pooling的工作机制 CAM Grad CAM 主要工作 CAM与Grad CAM用于解释CNN模型 这两个算法均可得出 c l a s s
  • 【JVM】Java垃圾回收机制(GC)详解

    Java垃圾回收机制 GC 详解 一 为什么需要垃圾回收 如果不进行垃圾回收 内存迟早都会被消耗空 因为我们在不断的分配内存空间而不进行回收 除非内存无限大 我们可以任性的分配不回收 但是事实并非如此 所以 垃圾回收是必须的 二 哪些内存需
  • 【kali】kali环境下安装dvwa

    STEP1 从github下载dvwa git clone https github com ethicalhack3r DVWA Q 我要自己安装git吗 A kali不用啦 一般都自带有 但是普通的ubuntu和debian上是没有的哦
  • Eclipse4.3 swt 插件在线安装

    到eclipse官网下载swt插件 1 点击该网站主菜单 Downloads gt Project 在出现的插件列表中找到 WindowBuilder 并点击 出现如下网页 复制该链接地址 当然该网页讲的就是如何安装swt designer
  • MATLAB地理数据处理 25:植被物候提取及分析模型优化(Savitzky-Golay)

    物候提取模型优化 1 前提 2 MATLAB代码 1 前提 之前我写过一篇使用Savitzky Golay处理遥感数据 获取地面物候信息的MATLAB代码 Python地理数据处理 十七 植被物候提取和分析 Savitzky Golay 但
  • MySQL数据表的约束

    数据表约束 对于某一列的值能添加哪些内容做了一定的限制 这种限制的手段就称为约束 一 约束的类型 NOT NULL 指示某列不能存储 NULL 值 UNIQUE 保证某列的每行必须有唯一的值 DEFAULT 规定没有给列赋值时的默认值 PR
  • Visual Studio 2022编译CMake工程

    用VS2022打开CMakeLists txt文件所在的文件夹 配置缓存 生成完毕 选择启动项 调试启动 运行输出 进入CMake项目视图 启动参数设置 增加args
  • Dll 编程入门指南

    我正在 学习 DLLs 谈不上对其有什么高屋建瓴的见解 本文只是 通过 编码让你看到并想知道代码是如何运行的 在本文中 我假定你知道如何使用你的编译器特性 比如设置目录路径等等 为了建立项目 请选择Win32 控制台项目 Win32 Con
  • 飞机游戏初步

    步骤 1 创建 hellogame项目 tools gt cocos2d console gt bin gt shift 右键 gt 在此处打开命令窗口 gt 路径pythoncocos py new hellogame p com gam
  • 一文说透 MySQL JSON 数据类型(收藏)

    JSON 数据类型是 MySQL 5 7 8 开始支持的 在此之前 只能通过字符类型 CHAR VARCHAR 或 TEXT 来保存 JSON 文档 相对字符类型 原生的 JSON 类型具有以下优势 在插入时能自动校验文档是否满足 JSON
  • 【日志脱敏】Springboot集成日志框架脱敏实战

    针对日志打印而不能泄露用户隐私需求 需要利用相应日志框架实现脱敏 本文基于log4j logback 重写相应方法 匹配出正则并转换为脱敏后的日志 效果展示如下 name 李 idNumber 110106 226X mobile 130