当前位置: 首页 > news >正文

日常记录-logback脱敏

logback添加如下配置:

 <!-- 自定义日志转换规则 -->

<conversionRule conversionWord="sensitived" converterClass="cn.framework.sensitive.SensitiveConverter" />

import ch.qos.logback.classic.pattern.MessageConverter;

import ch.qos.logback.classic.spi.ILoggingEvent;

import org.apache.commons.collections.CollectionUtils;

import org.apache.commons.lang.StringUtils;

import java.util.Arrays;

import java.util.List;

import java.util.regex.Matcher;

import java.util.regex.Pattern;

import java.util.stream.Collectors;

public class SensitiveConverter extends MessageConverter {

    /**

     * 日志脱敏开关

     */

    private static boolean converterCanRun = true;

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

    @Override

    public String convert(ILoggingEvent event) {

        // 原始日志

        String oriLogMsg = event.getFormattedMessage();

        try {

            // 日志脱敏处理

            return invokeMsg(oriLogMsg);

        } catch (Exception e) {

            return oriLogMsg;

        }

    }

    /**

     * 日志脱敏处理

     *

     * @return 脱敏后的日志

     */

    private String invokeMsg(final String oriMsg) {

        if (!converterCanRun) {

            return oriMsg;

        }

        if (StringUtils.isBlank(oriMsg) || oriMsg.length() > 5000) {//太长就不脱敏了,处理慢,存在风险

            return oriMsg;

        }

        String tempMsg = oriMsg;

        // 处理字符串

        List<SensitiveFieldEnum> sensitiveFieldEnumList = Arrays.stream(SensitiveFieldEnum.values()).collect(Collectors.toList());

        if (CollectionUtils.isNotEmpty(sensitiveFieldEnumList)) {

            for (SensitiveFieldEnum fieldEnum : sensitiveFieldEnumList) {

                String fieldName = fieldEnum.getFieldName();

                int index = -1;

                do {

                    index = StringUtils.indexOfIgnoreCase(tempMsg, fieldName, index + 1);

                    if (index != -1) {

                        // 判断key是否为单词字符

                        if (isWordChar(tempMsg, fieldName, index)) {

                            continue;

                        }

                        // 寻找值的开始位置

                        int valueStart = getValueStartIndex(tempMsg, index + fieldName.length());

                        // 查找值的结束位置........................

                        int valueEnd = getValuEndIndex(tempMsg, valueStart);

                        // 对获取的值进行脱敏

                        String subStr = tempMsg.substring(valueStart, valueEnd);

                        //脱敏处理

                        subStr = fieldEnum.desensitizationProcessing(subStr);

                        tempMsg = tempMsg.substring(0, valueStart) + subStr + tempMsg.substring(valueEnd);

                    }

                } while (index != -1);

            }

        }

        return tempMsg;

    }

    /**

     * 判断从字符串msg获取的key值是否为单词 , index为key在msg中的索引值

     */

    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 + "");

        return match.matches();

    }

    /**

     * 获取value值的开始位置

     *

     * @param msg 要查找的字符串

     * @param valueStart 查找的开始位置

     */

    private int getValueStartIndex(String msg, int valueStart) {

        // 寻找值的开始位置.................................

        do {

            char ch = msg.charAt(valueStart);

            if (ch == ':' || ch == ':' || ch == '=') { // key与 value的分隔符

                valueStart++;

                ch = msg.charAt(valueStart);

                if (ch == '"' || ch == '\'') {

                    valueStart++;

                }

                break; // 找到值的开始位置

            } else {

                valueStart++;

            }

        } while (true);

        return valueStart;

    }

    /**

     * 获取value值的结束位置

     */

    private int getValuEndIndex(String msg, int valueEnd) {

        do {

            if (valueEnd == msg.length()) {

                break;

            }

            char ch = msg.charAt(valueEnd);

            if (ch == '"' || 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 == ',' || ch == ',' || ch == '}') {

                break;

            } else {

                valueEnd++;

            }

        } while (true);

        return valueEnd;

    }

}

 

public enum SensitiveFieldEnum {

    //银行卡号

    BANKACCOUNT("BANKACCOUNT", "银行卡号"),

    NEWBANKACCOUNT("NEWBANKACCOUNT", "新卡号")

    ;

    private String fieldName;//字段名

    private String fieldDescribe;//字段描述

    public String getFieldName() {

        return fieldName;

    }

    public String getFieldDescribe() {

        return fieldDescribe;

    }

    SensitiveFieldEnum(String fieldName, String fieldDescribe) {

        this.fieldName = fieldName;

        this.fieldDescribe = fieldDescribe;

    }

    public String desensitizationProcessing(String data) {

        try {

            return DataDesensitizationUtil.generic(data);

        } catch (Exception e) {

            return data;

        }

    }

}

import org.apache.commons.lang.StringUtils;

public class DataDesensitizationUtil {

    private static final String S = "*";

    private static final String SSS = "***";

    // 通用脱敏

    public static String generic(String data) {

        return fullDesensitize(data);

    }

    // 通用全部脱敏方法,只显示开始和结束的部分

    private static String fullDesensitize(String data) {

        if (StringUtils.isBlank(data) || StringUtils.equals(data, "null") || StringUtils.equals(data, "<null>")) {

            return data;

        }

        data = data.trim();//去除前后空格

        int initLength = data.length();

        if (initLength >= 20) {

            return data.substring(0, 6) + SSS + data.substring(initLength - 6);

        }

        if (initLength >= 15) {//银行卡16到19位、身份证15、18位

            return data.substring(0, 6) + SSS + data.substring(initLength - 4);

        }

        if (initLength >= 10) {//手机号11位

            return data.substring(0, 3) + SSS + data.substring(initLength - 4);

        }

        if (initLength >= 8) {

            return data.substring(0, 2) + SSS + data.substring(initLength - 4);

        }

        if (initLength >= 5) {

            return SSS + data.substring(initLength - 3);

        }

        if (initLength >= 3) {//姓名3、4位

            return S + data.substring(initLength - 2);

        }

        if (initLength >= 2) {//姓名2位

            return S + data.substring(initLength - 1);

        }

        return data;

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

相关文章:

  • 准确--CentOS 7 配置 Chrony 同步阿里云 NTP 时间服务器及手动同步指南
  • 代理设计模式:从底层原理到源代码的详细解释
  • opencv图像的梯度处理,边缘检测
  • 基于国产 FPGA+ 龙芯2K1000处理器+翼辉国产操作系统继电保护装置测试装备解决方案
  • 联邦元学习实现个性化物联网的框架
  • 类加载器与jvm的内存
  • 【数学建模】孤立森林算法:异常检测的高效利器
  • 3.1goweb框架gin下
  • 大模型学习笔记------Llama 3模型架构之分组查询注意力(GQA)
  • 轻量级别的htpp客户端--Forest
  • Mysql 读写分离(3)之 schema.xml基本配置
  • Linux系统之----进程的概念
  • 【动手学强化学习】番外8-IPPO应用框架学习与复现
  • [预备知识]4. 概率基础
  • DES、3DES、SM4 加密算法简介
  • 【RuleUtil】适用于全业务场景的规则匹配快速开发工具
  • Post-Processing PropertySource instance详解 和 BeanFactoryPostProcessor详解
  • 信息系统项目管理师_第十三章 项目干系人管理
  • MySQL 双主复制架构入门
  • Sentinel数据S2_SR_HARMONIZED连续云掩膜+中位数合成
  • 清华数字政府与治理研究院揭牌:服务数字政府建设需求
  • 伊朗阿巴斯港港口爆炸已致47人受伤
  • 如何做大中国拳击产业的蛋糕?这项赛事给出办赛新思考
  • 经济日报金观平:充分发挥增量政策的经济牵引力
  • 博物馆有一项活动40岁以上不能参加?馆方回应
  • 蚂蚁集团将向全体股东分红