工具类篇【四】日志脱敏 桃扇骨 2022-12-08 04:51 134阅读 0赞 **工具类篇大全** **[工具类篇【一】String字符串][String]** **[工具类篇【二】BigDecimal计算][BigDecimal]** **[工具类篇【三】日期Date转换][Date]** **[工具类篇【四】日志脱敏][Link 1]** **[工具类篇【五】Random随机生成字符串][Random]** **[工具类篇【六】克隆对象的2种常用方法][2]** -------------------- ### 前言 ### 随着科技和信息化时代的加速发展,尤其在5G和大数据时代的今天,信息安全也逐渐成为人民更为关注的事情。为用户和会员保护个人隐私信息显得尤为重要。对于一些敏感数据的展示和存储,公司安全部门经常要求加密或脱敏处理。对敏感数据进行MD5加密存储,前端和日志脱敏处理。如:身份证、手机号、姓名、地址等,尤其是对敏感数据安全性要求较高行业和公司;电商、通信、金融等行业。 ### 一、logback工具包 ### 今天主要讲述后台系统对于敏感数据进行日志脱敏处理,拿来即用的工具实现类。利用logback工具包的日志脱敏处理,非常简单和方便。主要分为以下几个步骤: * 定义脱敏日志关键字 * 获取关键字开始索引位置 * 获取关键字结束索引位置 * 进行关键字脱敏处理 日志脱敏处理主工具类: package **.util; import ch.qos.logback.classic.pattern.MessageConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import com.google.common.collect.Lists; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @Author: ** * @Date: 2020/9/17 10:18 * @param: 数据脱敏处理转换类【logback包】 * @return: */ public class SensitiveDataConverter extends MessageConverter { /** * 日志脱敏开关 */ private static String converterCanRun = "true"; /** * 日志脱敏关键字 */ private static String sensitiveDataKeys = "idcard,realname,bankcard,mobile,shipAddress,detailedAddr,customerName,shipAddriess"; private static Pattern pattern = Pattern.compile("[0-9a-zA-Z]"); @Override public String convert(ILoggingEvent event){ // 获取原始日志 String oriLogMsg = event.getFormattedMessage(); // 获取脱敏后的日志 String afterLogMsg = invokeMsg(oriLogMsg); return afterLogMsg; } /** * 处理日志字符串,返回脱敏后的字符串 * @param: msg * @return */ public static String invokeMsg(final String oriMsg){ String tempMsg = oriMsg; if("true".equals(converterCanRun)){ // 处理字符串 if(sensitiveDataKeys != null && sensitiveDataKeys.length() > 0){ String[] keysArray = sensitiveDataKeys.split(","); for(String key: keysArray){ int index= -1; do{ index = tempMsg.indexOf(key, index+1); if(index != -1){ // 判断key是否为单词字符 if(isWordChar(tempMsg, key, index)){ continue; } // 寻找值的开始位置 int valueStart = getValueStartIndex(tempMsg, index + key.length()); // 查找值的结束位置(逗号,分号)........................ int valueEnd = getValuEndEIndex(tempMsg, valueStart); // 对获取的值进行脱敏 String subStr = tempMsg.substring(valueStart, valueEnd); subStr = tuomin(subStr, key); /// tempMsg = tempMsg.substring(0,valueStart) + subStr + tempMsg.substring(valueEnd); } }while(index != -1); } } } return tempMsg; } /** * 判断从字符串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 == ','){ // 去掉前面的 \ 处理这种形式的数据 while(valueEnd>0 ){ char preCh = msg.charAt(valueEnd-1); if(preCh != '\\'){ break; } valueEnd--; } break; }else{ valueEnd ++; } }else if (ch ==';' || ch == ',' || ch == '}'){ break; }else{ valueEnd ++; } }while(true); return valueEnd; } /** * 调用脱敏工具类进行字段日志处理 * @param submsg * @param key * @return */ private static String tuomin(String submsg, String key){ // idcard:身份证号, realname:姓名, bankcard:银行卡号, mobile:手机号,attribute10,shipAddress,detailedAddr:地址 if("idcard".equals(key)){ return SensitiveInfoUtils.idCardNum(submsg); } if(Lists.newArrayList("realname","customerName").equals(key)){ return SensitiveInfoUtils.chineseName(submsg); } if("bankcard".equals(key)){ return SensitiveInfoUtils.bankCard(submsg); } if("mobile".equals(key)){ return SensitiveInfoUtils.mobilePhone(submsg); } if(Lists.newArrayList("attribute10","shipAddress","detailedAddr","shipAddriess").contains(key)){ return SensitiveInfoUtils.address(submsg); } return ""; } public static void main(String[] args) { String tempMsg = "{sign=f88898b2677e62f1ad54b9e330c0a27e, idcard=130333198901192762, realname=%E5%BE%90%E5%BD%A6%E5%A8%9C, key=c5d34d4c3c71cc45c88f32b4f13da887, mobile=13210141605, bankcard=6226430106137525}"; String tempMsg1 = "{\"reason\":\"成功 \",\"result\":{\"jobid\":\"JH2131171027170837443588J6\",\"realname\":\"李哪娜\",\"bankcard\":\"6226430106137525\",\"idcard\":\"130333198901192762\",\"mobile\":\"13210141605\",\"res\":\"1\",\"message\":\"验证成功\"},\"error_code\":0}"; String shipAddress ="{shipAddress=宁夏回族自治区.银川市.金凤区.长城中路街道收货人:+卜广龙手机号码:+13992283627}"; String detailedAddr ="{\"attribute10\":\"浙江省.杭州市.桐庐县.桐君街道.收货人: 陈静手机号码: 15168393010所在地区: 浙江省杭州市桐庐县城南街道详细地址: 白云源路1618号银通汽车4楼\"}"; SensitiveDataConverter sc = new SensitiveDataConverter(); System.out.println(sc.invokeMsg(tempMsg)); System.out.println(sc.invokeMsg(tempMsg1)); System.out.println(sc.invokeMsg(shipAddress)); System.out.println(sc.invokeMsg(detailedAddr)); } } ### 二、关键字处理工具类 ### 针对需要脱敏的关键字进行逐个个性化处理,也可定义方法动态传入关键字进行脱敏处理: package com.vip.fcs.app.ar.util; import org.apache.commons.lang3.StringUtils; /** * @Author: ** * @Date: 2020/9/17 10:23 * @param: 数据脱敏处理工具类 * @return: */ public class SensitiveInfoUtils { /** * [姓名] 只显示第一个汉字,其他隐藏为星号<例子:李**> * * @param fullName * @return */ public static String chineseName(String fullName) { if (StringUtils.isBlank(fullName)) { return ""; } String name = StringUtils.left(fullName, 1); return StringUtils.rightPad(name, StringUtils.length(fullName), "*"); } /** * [身份证号] 显示最后四位,其他隐藏。共计18位或者15位。<例子:*************5762> * * @param idCardNum * @return */ public static String idCardNum(String idCardNum) { if (StringUtils.isBlank(idCardNum)) { return ""; } String num = StringUtils.right(idCardNum, 4); return StringUtils.leftPad(num, StringUtils.length(idCardNum), "*"); } /** * [手机号码] 前三位,后四位,其他隐藏<例子:138******1234> * * @param num * @return */ public static String mobilePhone(String num) { if (StringUtils.isBlank(num)) { return ""; } return StringUtils.left(num, 3).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(num, 4),StringUtils.length(num), "*"), "***")); } /** * [银行卡号] 前六位,后四位,其他用星号隐藏每位1个星号<例子:6222600**********1234> * * @param cardNum * @return */ public static String bankCard(String cardNum) { if (StringUtils.isBlank(cardNum)) { return ""; } return StringUtils.left(cardNum, 6).concat(StringUtils.removeStart(StringUtils.leftPad(StringUtils.right(cardNum, 4), StringUtils.length(cardNum), "*"), "******")); } /** * [会员地址] 前六位,其他用星号隐藏每位1个星号<例子:广东省广州市*******> * * @param:cardNum * @return */ public static String address(String address) { if (StringUtils.isBlank(address) || address.length() <9) { return ""; } String name = StringUtils.left(address, 9); return StringUtils.rightPad(name, StringUtils.length(address), "*********"); } } [String]: https://blog.csdn.net/xuri24/article/details/108760876 [BigDecimal]: https://blog.csdn.net/xuri24/article/details/108760241 [Date]: https://blog.csdn.net/xuri24/article/details/108739533 [Link 1]: https://blog.csdn.net/xuri24/article/details/108652118 [Random]: https://blog.csdn.net/xuri24/article/details/84790915 [2]: https://blog.csdn.net/xuri24/article/details/108087720
还没有评论,来说两句吧...