logback⽇志实现敏感数据脱敏
在l 中 添加
<conversionRule conversionWord="msg" converterClass="utils.SensitiveDataConverter"> </conversionRule>
import ch.qos.logback.classic.pattern.MessageConverter;
import ch.qos.logback.classic.spi.ILoggingEvent;
llect.Lists;
import s.lang3.StringUtils;
import Matcher;
import Pattern;
银行客户经理年终总结/**
* 敏感信息脱敏处理
* @author AAA
*/
public class SensitiveDataConverter extends MessageConverter {
/**
* ⽇志脱敏开关
*/
private static String converterCanRun = "true";
/**
* ⽇志脱敏关键字
*/
private static String nsitiveDataKeys = "idCard,dTel,dMobile,dAddress,jMobile,jAddress,address,phone";
private static Pattern pattern = pile("[0-9a-zA-Z]");
//⼿机号正则匹配
private static final String PHONE_REGEX = "1[3|4|5|6|7|8|9][0-9]\\d{8}";
//⾝份证号正则匹配
又得浮生一日凉private static final String IDCARD_REGEX = "([1-9]\\d{5}(18|19|20)\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3}[0-9Xx])|(^[1-9]\\d{5}\\d{2} ((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3})";
//之所以定义这个参数,完全是处于公司的要求,因为公司要求敏感信息在⽇志输出时被脱敏后,还能按照⼀定的规则还原,所以就⽤这些字母来进⾏处理了,对于没有这种要求的,就更简单了,直接⽤*去脱敏就可以了,⼤家很容易根据现在的代码进⾏改造,这⾥不在多讲
private static final String KEY = "axedfqLGpu";
@Override
public String convert(ILoggingEvent event){
/
/ 获取原始⽇志
String oriLogMsg = FormattedMessage();
// 获取脱敏后的⽇志
String afterLogMsg = invokeMsg(oriLogMsg);
// return afterLogMsg;
return filterSensitive(afterLogMsg);
}
/**
* 处理⽇志字符串,返回脱敏后的字符串
* @param: msg
* @return
*/
public static String invokeMsg(final String oriMsg){
String tempMsg = oriMsg;
if("true".equals(converterCanRun)){
最贵的茶if("true".equals(converterCanRun)){
// 处理字符串
都江堰景区门票
if(nsitiveDataKeys != null && nsitiveDataKeys.length() > 0){
String[] keysArray = nsitiveDataKeys.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 fal;
}
/**
* 获取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的分隔符
if(ch == ':' || ch == '='){ // key与 value的分隔符
valueStart ++;
ch = msg.charAt(valueStart);
if(ch == '"'){
valueStart ++;
}
break; // 找到值的开始位置
}el{
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;
}el{
valueEnd ++;
}
}el if (ch ==';' || ch == ',' || ch == '}'){
break;
}el{
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:地址 wArrayList("idCard","id_card").contains(key)){
return SensitiveInfoUtils.idCardNum(submsg);
}
// wArrayList("realname","customerName").equals(key)){
// return SensitiveInfoUtils.chineName(submsg);
// return SensitiveInfoUtils.chineName(submsg);
// }
wArrayList("dTel","","dMobile","","jMobile","","phone").contains(key)){ bilePhone(submsg);
}
wArrayList("dAddress","","jAddress","","address").contains(key)){
return SensitiveInfoUtils.address(submsg,3);
}
return "";
}
// @Override
// public String convert(ILoggingEvent event){
//
// // 获取原始⽇志
// String requestLogMsg = FormattedMessage();
//
/
/ // 获取返回脱敏后的⽇志
// return filterSensitive(requestLogMsg);
// }
/**
* 对敏感信息脱敏
* @param content
* @return
* @author ljh
* @date 2019年12⽉17⽇
*/
public static String filterSensitive(String content) {
try {
if(StringUtils.isBlank(content)) {
return content;
}
content = filterIdcard(content);
return filterMobile(content);
}catch(Exception e) {
return content;
}
}
/**
* [⾝份证号] 指定展⽰⼏位,其他隐藏。<;例⼦:1101**********5762>
* @param num
* @return
* @author ljh
* @date 2019年12⽉18⽇
*/
private static String filterIdcard(String num){
Pattern pattern = pile(IDCARD_REGEX);
Matcher matcher = pattern.matcher(num);
StringBuffer sb = new StringBuffer() ;
while(matcher.find()){
matcher.appendReplacement(sb, up(), 4, 4)); }
matcher.appendTail(sb) ;
String();
}
/**
* [⼿机号码] 前三位,后四位,其他隐藏<;例⼦:138******1234>
* @param num
* @return
* @return
* @author ljh
人性底线* @date 2019年12⽉18⽇
*/
private static String filterMobile(String num){
Pattern pattern = pile(PHONE_REGEX);
Matcher matcher = pattern.matcher(num);
StringBuffer sb = new StringBuffer() ;
while(matcher.find()){
matcher.appendReplacement(sb, up(), 3, 4)) ;
}
matcher.appendTail(sb) ;
String();
}
/
**
* 基础脱敏处理指定起⽌展⽰长度剩余⽤"KEY"中字符替换
*戈夫曼
* @param str 待脱敏的字符串
* @param startLength 开始展⽰长度
* @param endLength 末尾展⽰长度
* @return 脱敏后的字符串
*/
private static String baSensitive(String str, int startLength, int endLength) {
if (StringUtils.isBlank(str)) {
return "";
}
String replacement = str.substring(startLength,str.length()-endLength);
StringBuffer sb = new StringBuffer();
for(int i=0;i<replacement.length();i++) {
char ch;
if(replacement.charAt(i)>='0' && replacement.charAt(i)<='9') {
ch = KEY.charAt((int)(replacement.charAt(i) - '0'));
}el {
ch = replacement.charAt(i);
}
sb.append(ch);
}
return StringUtils.left(str, startLength).concat(StringUtils.leftPad(StringUtils.right(str, endLength), str.length() - startLength, sb.toString())); }
/**
藏族踢踏舞* 按"KEY"中字符解密
* @param str
* @param startLength
* @param endLength
* @return
* @author ljh
* @date 2019年12⽉18⽇
*/
private static String decrypt(String str, int startLength, int endLength) {
if (StringUtils.isBlank(str)) {
return "";
}
String replacement = str.substring(startLength,str.length()-endLength);
StringBuffer sb = new StringBuffer();
for(int i=0;i<replacement.length();i++) {
int index = KEY.indexOf(replacement.charAt(i));
if(index != -1) {
sb.append(index);
精简人员}el {
sb.append(replacement.charAt(i));
}
}
return StringUtils.left(str, startLength).concat(StringUtils.leftPad(StringUtils.right(str, endLength), str.length() - startLength, sb.toString())); }