Java 加载Properties 配置文件:

        ResourceBundle bundle = ResourceBundle.getBundle("log4j_filter"); // 不要写扩展名  .properties
        LOG_FILTER_SWITH = bundle.getString("log4j.filter.swith");
        LOG_FILTER_KEYS = bundle.getString("log4j.filter.keys");

    // 直接在本类中使用main调用时用 Properties.class.getResourceAsStream("/log4j_filter.properties");
    //Properties p = new Properties();
    //p.load(in);
    //LOG_FILTER_SWITH = p.getProperty("log4j.filter.swith");
    //LOG_FILTER_KEYS = p.getProperty("log4j.filter.keys");


日志脱敏实现: 因为只修改了一个log4j类的调用,故日志必须是

    private final static Logger logger = LogManager.getLogger(SeqConfControl.class);
1 , 配置文件 log4j_filter.properties (一个参数是脱敏日志开关, 一个参数是要脱敏的关键字)
2,自定义类  :     org.apache.logging.log4j.spi.Log4jFilter.java 是解析处理日志字符串中的敏感信息;
      log4j原生类: org.apache.logging.log4j.spi.AbstractLogger.java  负责调用自己写的类的方法.
 
3, 规则   支持k:v  和  k=v  两种形式的数据处理
                 脱敏时v的长度如果大于8,  采用   XXX****XXX的形式脱敏;  如果小于等于8采用  ******* 形式脱敏
 
效果:
20:25:02,0197 [INFO ][ ][connect to SFTP . ip:10.0.26.36; port:22;uppath:null;downpath:home/selfftp/selffile/20161209/;username:selfftp;password:********][ :][hulk.frame.sftp.SFtpTools]

21:06:16,0907 [INFO ][ ][接收到一个纯文本消息并开始传入数据库:{"data":"{\"state\":\"0\",\"hostName\":\"termfrontapp\",\"policyName\":\"check_SSPM_101\",\"stateName\":null,\"program\":null,\"entryId\":null,\"agentId\":null,\"msg\":\"{\\\"account_num\\\":\\\"62294785200****0034\\\",\\\"amount\\\":\\\"2.00\\\",\\\"channel_id\\\":\\\"01I\\\",\\\"p_trans_code\\\":\\\"1017006\\\",\\\"card_type\\\":\\\"\\\",\\\"start_time\\\":\\\"1481634017288\\\",\\\"end_time\\\":\\\"1481634017526\\\",\\\"term_id\\\":\\\"01159206\\\",\\\"ret_code\\\":\\\"ZZ\\\",\\\"ret_msg\\\":\\\"交易失败,请联系发卡方|Transaction failed, please contact the issuser\\\",\\\"trans_date_sspm\\\":\\\"20161213210017\\\",\\\"term_install_addr\\\":\\\"10.0.66.8-->10.0.54.198\\\",\\\"term_inst_id\\\":\\\"238\\\",\\\"p_trans_describe\\\":\\\"贷款还息\\\",\\\"account_id2\\\":\\\"\\\"}\",\"ip\":\"10.0.26.71\",\"policyId\":null}","taskClass":"stateAlarm"}][ :][hulk.sspm.trandataMonitor.util.ConsumerMessageListener]
21:06:16,0907 [INFO ][ ][the message to decode: {"account_num":"62294785200****0034","amount":"2.00","channel_id":"01I","p_trans_code":"1017006","card_type":"","start_time":"1481634017288","end_time":"1481634017526","term_id":"01159206","ret_code":"ZZ","ret_msg":"交易失败,请联系发卡方|Transaction failed, please contact the issuser","trans_date_sspm":"20161213210017","term_install_addr":"10.0.66.8-->10.0.54.198","term_inst_id":"238","p_trans_describe":"贷款还息","account_id2":""}]

log4j_filter.properties:

# log4j 过滤器配置文件,主要用于系统中敏感字段的脱敏

# true表示打开   false表示关闭
log4j.filter.swith=true
# 要脱敏的关键字
log4j.filter.keys=password,passwd,password1,password2,account_num

自定义解析类:org.apache.logging.log4j.spi.Log4jFilter.java

package org.apache.logging.log4j.spi;

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

/**
 * 自定义处理 日志中的敏感信息
 * @author yangw1006@163.com
 *
 */
public class Log4jFilter {

    /**
     * 日志脱敏 开关
     */
    private static String LOG_FILTER_SWITH = "false";
    /**
     * 日志脱敏关键字
     */
    private static String LOG_FILTER_KEYS = null;
    static{
        // 加载配置文件
        try {
            // 直接在本类中使用main调用时用 Properties.class.getResourceAsStream("/log4j_filter.properties");
            //InputStream in =Properties.class.getClassLoader().getResourceAsStream("log4j_filter.properties");
            //Properties p = new Properties();
            //p.load(in);
            //LOG_FILTER_SWITH = p.getProperty("log4j.filter.swith");
            //LOG_FILTER_KEYS = p.getProperty("log4j.filter.keys");
            ResourceBundle bundle = ResourceBundle.getBundle("log4j_filter");
            LOG_FILTER_SWITH = bundle.getString("log4j.filter.swith");
            LOG_FILTER_KEYS = bundle.getString("log4j.filter.keys");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理日志字符串,返回脱敏后的字符串
     * @param msg
     * @return
     */
    public static String invokeMsg(final String message){

        String msg = new String(message);
        if("true".equals(LOG_FILTER_SWITH)){
            //处理字符串
            if(LOG_FILTER_KEYS!=null && LOG_FILTER_KEYS.length()>0){

                String[] keyArr = LOG_FILTER_KEYS.split(",");
                for(String key: keyArr){
                    // 找key
                    int index= -1;
                    do{
                        index = msg.indexOf(key, index+1);
                        if(index!=-1){
                            // 判断key是否为单词字符
                            if(isWordChar(msg,key,index)){
                                continue;
                            }
                            // 确定是单词无疑....................................
                            // 寻找值的开始位置.................................
                            int valueStart = getValueStartIndex(msg,index + key.length());

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

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

                }
            }
        }

        return msg;
    }

    private static Pattern pattern = Pattern.compile("[0-9a-zA-Z]");
    /**
     * 判断从字符串msg获取的key值是否为单词 , index为key在msg中的索引值
     * @return
     */
    private static 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 static 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 static 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 == ','){
                    // 去掉前面的 \  处理这种形式的数据 "account_num\\\":\\\"6230958600001008\\\"
                    while(valueEnd>0 ){
                        char preCh = msg.charAt(valueEnd-1);
                        if(preCh != '\\'){
                            break;
                        }
                        valueEnd--;
                    }
                    break;
                }else{
                    valueEnd ++;
                }
            }else if (ch ==';' || ch == ','){
                break;
            }else{
                valueEnd ++;
            }

        }while(true);

        return valueEnd;
    }

    private static String tuomin(String submsg){

        StringBuffer sbResult = new StringBuffer();
        if(submsg!=null && submsg.length()>0){
            int len = submsg.length();
            if(len > 8){ //8位以上的    隐掉中间4位
                for(int i = len-1;i>=0;i--){
                    if(len-i<5 || len-i>8){
                        sbResult.insert(0, submsg.charAt(i));
                    }else{
                        sbResult.insert(0, '*');
                    }
                }
            }else{ //8位以下的全部使用 *
                for(int i =0;i<len;i++){
                    sbResult.append('*');
                }
            }
        }
        return sbResult.toString();
    }

    public static void main (String[] args) {
        //{\\\"account_num\\\":\\\"6230958600001008\\\",\\\"amount\\\":\\\"\\\"
        String msg = "\\\"account_num\\\":\\\"6230958600001008\\\",\\\"amount\\\":\\\"\\\"";
        System.out.println(invokeMsg(msg));

    }
}

log4j原生类 org.apache.logging.log4j.spi.AbstractLogger.java 修改的地方

 # 代码 725行左右的方法
 protected void logMessage(final String fqcn, final Level level, final Marker marker, final String message, final Throwable t) {
        // by yangw
        String invokeMsg = Log4jFilter.invokeMsg(message);
        logMessage(fqcn, level, marker, messageFactory.newMessage(invokeMsg), t);
    }

log4j 日志脱敏处理 + java properties文件加载的更多相关文章

  1. 161216、使用spring的DefaultResourceLoader自定义properties文件加载工具类

    import java.io.IOException; import java.io.InputStream; import java.util.NoSuchElementException; imp ...

  2. 使用spring的DefaultResourceLoader自定义properties文件加载工具类

    转自:https://www.cnblogs.com/zrbfree/p/6230957.html import java.io.IOException; import java.io.InputSt ...

  3. Java实现配置加载机制

    前言 现如今几乎大多数Java应用,例如我们耳熟能详的tomcat, struts2, netty…等等数都数不过来的软件,要满足通用性,都会提供配置文件供使用者定制功能. 甚至有一些例如Netty这 ...

  4. jdbc.properties不能加载到tomcat项目下面

    javaweb项目的一个坑,每次重启tomcat都不能将项目中的jdbc.properties文件加载到tomcat项目对应的classes目录下面,得手动粘贴到该目录下.

  5. Java基础之Throwable,文件加载

    Java中的异常与错误都继承自Throwable,Exception又分为运行时异常(RuntimeException)和编译时异常. 运行时异常是程序的逻辑不够严谨或者特定条件下程序出现了错误,例如 ...

  6. Java 使用properties配置文件加载配置

    一般我们不把数据库的配置信息写死在代码中. 写好代码后,编译.调试,成功后只把输出目录中的东西(jar包..class文件.资源文件等)拷贝到服务器上,由运维来管理.服务器上是没有源文件的(.java ...

  7. Java中的资源文件加载方式

    文件加载方式有两种: 使用文件系统自带的路径机制,一个应用程序只能有一个当前目录,但可以有Path变量来访问多个目录 使用ClassPath路径机制,类路径跟Path全局变量一样也是有多个值 在Jav ...

  8. Android 的 so 文件加载机制

    本篇文章已授权微信公众号 guolin_blog (郭霖)独家发布 最近碰到一些 so 文件问题,顺便将相关知识点梳理一下. 提问 本文的结论是跟着 System.loadlibrary() 一层层源 ...

  9. 插件化框架解读之so 文件加载机制(四)

    阿里P7移动互联网架构师进阶视频(每日更新中)免费学习请点击:https://space.bilibili.com/474380680 提问 本文的结论是跟着 System.loadlibrary() ...

随机推荐

  1. WSGIweb框架--1

    from multiprocessing import Process import re import sys import socket #设置静态文件根目录 HTML_ROOT_DIR = '. ...

  2. CentOS自带mysql配置(密码更改、端口开放访问、添加进系统启动项)

    前些天虚拟机安装好了CentOS6.1,但是自己想远程连接自带的mysql发现不知道如何改密码,于是谷歌一下,把结果记录下来,方便后期自己使用: 方法一: # /etc/init.d/mysql st ...

  3. 2017-4-25/设计缓存(LFU)

    1. 恒定缓存性能有哪些因素? 命中率.缓存更新策略.缓存最大数据量. 命中率:指请求缓存次数和缓存返回正确结果次数的比例.比例越高,缓存的使用率越高,用来衡量缓存机智的好坏和效率.如果数据频繁更新, ...

  4. Java设计模式 (转)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  5. PyQt5实现透明电子时钟

    # -*- coding: utf-8 -*- import sys from PyQt5 import QtCore from PyQt5 import QtGui from PyQt5 impor ...

  6. [2016-07-15]结合命令行工具awk和多行文本编辑器快速生成DataSeed代码

    目标:根据业务提供的两份数据,生成DataSeed代码 SampleDataA 上海 华东一线 上饶 华东四线 中山 华南二线 临汾 华北四线 临沂 华东二线 SampleDataB 上海 1D04E ...

  7. 表单校验demo

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 【RN6752】模拟高清AHD芯片或成为车机新标配

    由于目前车机方案倒车后视目前大多为480P标配,画面噪点多有锯齿成像效果差,成为行业的难言之痛.2012年底,浙江大华宣布发布一项具备完全自主知识产权的安防行业高清视频传输规范--HDCVI--Hig ...

  9. ssh的相关实验

    author:JevonWei 版权声明:原创作品 跨主机ssh连接 主机A想连接主机C,但是主机C防火墙等原因禁止主机A连接,而主机A可以连接主机B,主机B也可连接主机C,即主机A就可通过主机B做跳 ...

  10. Java异常的性能分析

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt276 在Java中抛异常的性能是非常差的.通常来说,抛一个异常大概会消耗10 ...