記錄一次logback的擴展

介紹

本文是一次數(shù)據(jù)泄漏之后的一點兒思考,系統(tǒng)日志對于后端系統(tǒng)而言是非常重要的丈积,但是大多數(shù)開發(fā)人員在打印日志時筐骇,是非常隨意的,不會去想太多江滨,覺得日志打印的越多铛纬,排查總是越是方便。但是一些關(guān)鍵信息在打印日志時一定要注意唬滑,如果這些信息被人利用告唆,可能會存在很大的風險。
下面我舉例幾個場景晶密,想想這樣的場景中存在的風險

1擒悬、用戶名、密碼稻艰、交易密碼等敏感信息懂牧,如果這些信息明文打印在日志,這些信息被人拿到之后尊勿,就存在很大的安全隱患归苍,這種隱患可能會直接導(dǎo)致用戶的損失,影響公司的形象运怖。

2拼弃、薪資系統(tǒng)中,姓名摇展、薪資等敏感信息吻氧,在每次列表、詳情查詢的時候不加考慮全部打印日志,只要有日志查看權(quán)限的人員中就可能查看到大部分人的薪資情況盯孙,導(dǎo)致公司薪資信息泄漏鲁森,可能會導(dǎo)致同一團隊的人員的薪資泄漏,造成人員流失等

其實對于這些場景振惰,我們只要在日志打印時歌溉,進行脫敏處理就可以,最近公司存在一起數(shù)據(jù)泄漏的事件骑晶,在這個事件之后痛垛,公司也比較重視這一塊,BOSS也因此很不開心桶蛔,在此事之后匙头,下班之余看了自己擴寫了一個日志脫敏的工具,因為公司內(nèi)部打印日志統(tǒng)一用的logback仔雷,本次擴展也是針對logback進行擴展

主要思路

每個團隊甚至每個人打印日志的習(xí)慣和風格都不一樣蹂析,基于日志格式輸出的多樣性,
所以本人覺得最好的辦法是通過配置脫敏規(guī)則碟婆,然后在日志輸出之前進行脫敏處理

整理了一下我們系統(tǒng)中日志打印的風格电抚,大數(shù)數(shù)是以下三種

  • log.info("xxxxx: {} " , JSONObject.toJsonString(result));
  • log.info("xxxxx: {} " , result );
  • log.info("xxxxxx: " + result );

實現(xiàn)過程

第一步:針對上述日志整理,我們先定義一下自己的脫敏規(guī)則竖共,增加配置文件logback-desensitization-rule.properties蝙叛,配置如下
這里需要一些正則的知識,大家請自行補一下

#JSON字段中的mobile , telphone關(guān)鍵字對應(yīng)的內(nèi)容進行脫敏
RULE_REG_1=(\"mobile\"|\"telphone\")(:\")(\\w{3})(\\w{4})(\\w{4})*(\")&$1$2$3****$5$6
#JSON字段中的"證件號碼"關(guān)鍵字對應(yīng)的內(nèi)容進行脫敏
RULE_REG_2=(\"idcard\")(:\")(\\w{2})(\\w{1,})(\\w{2})(\")&$1$2$3*********$5$6
#JSON字段中的"密碼"對應(yīng)的內(nèi)容進行全部*顯示 
RULE_REG_3=(\"password\")(:\")(\\w+)(\")&$1$2*****$4
#JSON字段中的"用戶名"對應(yīng)的內(nèi)容除第一位肘迎,其它位脫敏顯示  
RULE_REG_4=(\"customerName\"|\"userName\"|\"name\")(:\")([\u4E00-\u9FA5]{1})[\u4E00-\u9FA5]{1,}(\")&$1$2$3**$4
#log.info("password:{}",password);類似這樣的日志甥温,關(guān)鍵字后的8位中,后五位脫敏顯示 
RULE_REG_5=(password|mobile)([:|=|,| ]+)(\\w{3})(\\w{5})&$1$2$3*****

第二步:繼承MessageConverter實現(xiàn)日志脫敏

package com.bk.framework.extension.logback;

import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
import com.google.common.collect.Lists;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ArrayUtils;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * @author BK
 * @version V2.0
 * @description: logback擴展消息轉(zhuǎn)換器  支持正則脫敏
 * @date 2019/6/1 21:23
 */
@Slf4j
public class DesensitizationMessageConverter extends MessageConverter {
    private static volatile List<RuleConfig> configList;

    @Override
    public String convert(ILoggingEvent event) {
        initRuleConfig();
        return doConvert(event);
    }

    /**
     * 初始化規(guī)則配置
     */
    private void initRuleConfig() {
        if (configList == null) {
            synchronized (DesensitizationMessageConverter.class) {
                if (configList == null) {
                    configList = Lists.newArrayList();
                    Map<String, String> propertyMap = ((LoggerContext) LoggerFactory.getILoggerFactory()).getCopyOfPropertyMap();
                    for (String s : propertyMap.keySet()) {
                        if (s.startsWith("RULE_REG_")) {
                            String[] array = propertyMap.get(s).split("&");
                            if (ArrayUtils.isNotEmpty(array) && array.length == 2) {
                                configList.add(new RuleConfig(array[0], array[1]));
                            }
                        }
                    }
                    log.info("desensitization rule config init end ! ");
                }
            }
        }
    }

    /**
     * 日志內(nèi)容轉(zhuǎn)換
     *
     * @param event
     * @return
     */
    private String doConvert(ILoggingEvent event) {
        String result = event.getFormattedMessage();
        if (configList != null) {
            for (RuleConfig ruleConfig : configList) {
                result = ruleConfig.apply(result);
            }
        } else {
            result = super.convert(event);
        }
        return result;
    }

    @Data
    private class RuleConfig {
        private String reg;
        private String replacement;

        RuleConfig(String reg, String replacement) {
            this.reg = reg;
            this.replacement = replacement;
        }

        String apply(String message) {
            return Pattern.compile(reg).matcher(message).replaceAll(replacement);
        }
    }
}

第三步:增加logback.xml文件妓布,整合規(guī)則與轉(zhuǎn)換邏輯

  • 1姻蚓、引入我們第一步配置的脫敏規(guī)則屬性文件(這里要注意,屬性的scope匣沼,默認是local狰挡,詳細配置可以參考logback官網(wǎng))
  • 2、配置我們第二步增加的轉(zhuǎn)換器释涛,同時配置conversionWord="xxx"加叁,當日志輸出的pattern中引用%xxx時,會通過此轉(zhuǎn)換順進日志輸出的轉(zhuǎn)換
    配置如下
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <property  scope="context" resource="./logback-desensitization-rule.properties"/>

    <conversionRule conversionWord="msg"
                    converterClass="com.bk.framework.extension.logback.DesensitizationMessageConverter"/>
    <conversionRule conversionWord="rid" converterClass="com.bk.framework.extension.logback.ClassicConverterExt"/>
    <property name="CONSOLE_LOG_PATTERN"
              value="%date{yyyy-MM-dd HH:mm:ss} | %boldYellow(%rid) | %highlight(%-5level) | %boldYellow(%thread) | %boldGreen(%logger) | %msg%n"/>
    <appender name="stdout" class="ch.qos.logback.core.ConsoleAppender">
        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
            <pattern>${CONSOLE_LOG_PATTERN}</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="stdout"/>
    </root>
</configuration>

測試效果

  1. 編輯測試類
package com.bk.framework.extension;

import lombok.extern.slf4j.Slf4j;

/**
 * @author BK
 * @version V2.0
 * @date 2019-06-03 23:43
 */
@Slf4j
public class ExtensionApplication {
    public static void main(String[] args) {
        log.info("mobile:{}", "13588889999");
        log.info("userInfo:{}", "{\n" + "            \"userName\":\"羅志祥\"唇撬,\n" + "            \"idcard\":\"321183197701017846\",\n" + "            \"password\":\"luozhixiang1234\",\n" + "            \"mobile\":\"18888888888\"\n" + "        }");
    }
}
  1. 運行main方法


    運行結(jié)果

可以看到它匕,只需要增加一個轉(zhuǎn)換器,配置幾個正則窖认,就可以實現(xiàn)日志的脫敏豫柬,希望可以幫到大家告希,相關(guān)的代碼參考logback日志脫敏V1版本,傳送門項目地址.

關(guān)于優(yōu)化的一點兒思路

其實到現(xiàn)在烧给,我們可以實現(xiàn)日志脫敏燕偶,但是做法有些丑陋,不是很美觀础嫡,可以推薦一個思路

通過DTD或得schema文件 指么,定義自己的XML格式文件

  • 設(shè)置對于json,xml榴鼎,等不同式日志的脫敏關(guān)鍵字的replacement等信息伯诬,主要目的是為了簡化配置,封裝正則的配置難度檬贰,后臺根據(jù)配置自動生成正則和替換規(guī)則
  • 在logback start時姑廉,解析配置文件缺亮,讀取配置生成相應(yīng)的正則翁涤,進行脫敏

另一種優(yōu)化的思路

增加注解,對需要脫敏的字段進行標記關(guān)鍵字 @Desensitization(type=Desensitization.NAME) //或者 MOBILE 等其它萌踱,可以自己定義葵礼,只是需要在和配置文件中的統(tǒng)一

  • 增加SpringBoot注解 EnableLogBackDesensitization(pageckage = "com.bk.test, com.bk.xxx")
  • 參考Spring的component-scan,進行 包路徑掃描并鸵,把相關(guān)的字段鸳粉,根據(jù)分類收集起來,對正則中關(guān)鍵字部分替換
  • 在收集完成之后打印日志時园担,進行脫敏

相關(guān)代碼會傳到我的github上届谈,相關(guān)的代碼參考logback日志脫敏V2版本,傳送門項目地址

一點兒建議

  1. 過大對象一般不建議打日志
    對于一些過大的對象弯汰,比如查詢列表的結(jié)果建議不要打印艰山,如果需要打印的話,建議在DEBUG級別打印
    一般這種日志咏闪,對于問題排查意義不大曙搬,而且這種日志導(dǎo)致日志文件巨增,同時如果日志被竊取會存在信息泄漏的風險
  2. 打印日志時一定要有危機意識
    哪些日志可以打印鸽嫂,如些日志打印會有風險纵装,一定要做到心里有數(shù)
  3. 打印error級別日志時,建議使用log.error("xxxxxx" ,e );
    不要使用log.error("xxxxxx" ,e.getMessage() );

參考資料

https://logback.qos.ch/manual/configuration.html

寫在最后

這點兒東西寫了三遍据某,簡書是不是最近有問題橡娄,圖片展示不了,沒有發(fā)布的內(nèi)容總是丟失癣籽,這已經(jīng)是第三遍了挽唉。

歡迎大家討論扳还,本人才疏學(xué)淺,有不正確的地方還請斧正橱夭。 個人博客已經(jīng)開通氨距,感覺興趣可以收藏下:http://albk.tech , 內(nèi)容會同步更新簡書

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末棘劣,一起剝皮案震驚了整個濱河市俏让,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茬暇,老刑警劉巖首昔,帶你破解...
    沈念sama閱讀 216,591評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異糙俗,居然都是意外死亡勒奇,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,448評論 3 392
  • 文/潘曉璐 我一進店門巧骚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赊颠,“玉大人,你說我怎么就攤上這事劈彪】⒈模” “怎么了?”我有些...
    開封第一講書人閱讀 162,823評論 0 353
  • 文/不壞的土叔 我叫張陵沧奴,是天一觀的道長痘括。 經(jīng)常有香客問我,道長滔吠,這世上最難降的妖魔是什么纲菌? 我笑而不...
    開封第一講書人閱讀 58,204評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮疮绷,結(jié)果婚禮上翰舌,老公的妹妹穿的比我還像新娘。我一直安慰自己矗愧,他們只是感情好灶芝,可當我...
    茶點故事閱讀 67,228評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唉韭,像睡著了一般夜涕。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上属愤,一...
    開封第一講書人閱讀 51,190評論 1 299
  • 那天女器,我揣著相機與錄音,去河邊找鬼住诸。 笑死驾胆,一個胖子當著我的面吹牛涣澡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丧诺,決...
    沈念sama閱讀 40,078評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼入桂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了驳阎?” 一聲冷哼從身側(cè)響起抗愁,我...
    開封第一講書人閱讀 38,923評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎呵晚,沒想到半個月后蜘腌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,334評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡饵隙,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,550評論 2 333
  • 正文 我和宋清朗相戀三年撮珠,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片金矛。...
    茶點故事閱讀 39,727評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡芯急,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出绷柒,到底是詐尸還是另有隱情志于,我是刑警寧澤涮因,帶...
    沈念sama閱讀 35,428評論 5 343
  • 正文 年R本政府宣布废睦,位于F島的核電站,受9級特大地震影響养泡,放射性物質(zhì)發(fā)生泄漏嗜湃。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,022評論 3 326
  • 文/蒙蒙 一澜掩、第九天 我趴在偏房一處隱蔽的房頂上張望购披。 院中可真熱鬧,春花似錦肩榕、人聲如沸刚陡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,672評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽筐乳。三九已至,卻和暖如春乔妈,著一層夾襖步出監(jiān)牢的瞬間蝙云,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,826評論 1 269
  • 我被黑心中介騙來泰國打工路召, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勃刨,地道東北人波材。 一個月前我還...
    沈念sama閱讀 47,734評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像身隐,于是被迫代替她去往敵國和親廷区。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 44,619評論 2 354

推薦閱讀更多精彩內(nèi)容