日常记录-logback脱敏

logback添加如下配置:

 

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 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, "")) {

            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;

    }

}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(java)