log日志过滤base64
项目中使用到了logback. 过滤不打印base64字符
新建日志处理类
/**
* logback, 替换日志中的base64编码
*/
public class Base64ReplaceLogbackLayout extends PatternLayout {
private static final Pattern IMAGE_BASE64_PATTERN = Pattern.compile("[A-Za-z\\d+/]{214}([A-Za-z\\d+/][A-Za-z\\d+/=]+|==)");
@Override
public String doLayout(ILoggingEvent event) {
String msg = super.doLayout(event);
// 替换图片 base64
Matcher imageBase64Matcher = IMAGE_BASE64_PATTERN.matcher(msg);
if(imageBase64Matcher.find()){
return imageBase64Matcher.replaceAll("[IMAGE BASE64]");
} else {
return msg;
}
}
}在logback中使用
<appender name="LOG-FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_DIR}/log.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>${LOG_DIR}/log.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
<maxFileSize>500MB</maxFileSize>
<totalSizeCap>30GB</totalSizeCap>
<maxHistory>10</maxHistory>
</rollingPolicy>
<layout class="boot.draco.autoconfig.log.Base64ReplaceLogbackLayout">
<pattern>${logPattern}</pattern>
</layout>
<encoder>
<pattern>${logPattern}</pattern>
<charset>UTF-8</charset>
</encoder>
</appender>在普通的类中使用
ublic class Base64Util {
public static final String base64Pattern = "^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$";
private static final Pattern IMAGE_BASE64_PATTERN = Pattern.compile("[A-Za-z\\d+/]{214}([A-Za-z\\d+/][A-Za-z\\d+/=]+|==)");
/**
* 判断是否是base64字符
*/
public static boolean isBase64(String str) {
return Pattern.matches(base64Pattern, str);
}
public static String replaceBase64(String str){
if(null == str || str.isEmpty()){
return str;
}
Matcher imageBase64Matcher = IMAGE_BASE64_PATTERN.matcher(str);
if(imageBase64Matcher.find()){
return imageBase64Matcher.replaceAll("[IMAGE BASE64]");
} else {
return str;
}
}
}处理日志中的敏感字符
/**
* 重写log4j的PatternLayout,实现日志信息中敏感信息的编码或加密
*/
@Slf4j
public class Log4jEncodeLayout extends PatternLayout {
/** 要匹配的正则表达式(身份证/银行卡) */
private Pattern patternChar;
/** 要匹配的正则表达式(姓名) */
private Pattern namepatternChar;
private int keys_length_char;// 要匹配关键字的数目
private String[] charKeys;
private static final String LOG4J_CHAR_KEYS="identityCode,cardId";
private void init(){
String str_char_keys = StringUtils.trim(LOG4J_CHAR_KEYS);
log.info("str_char_keys :{}",str_char_keys);
if(!StringUtils.isEmpty(str_char_keys)){//没有配置log4j.char.keys,不需要替换*
charKeys = str_char_keys.split(",");// 读取配置中要加密的key
// 组织正则表达式
StringBuffer sbRegChar = new StringBuffer();
sbRegChar.append("(");
for (int i = 0; i < charKeys.length; i++) {
sbRegChar.append("(");
sbRegChar.append(charKeys[i]);
sbRegChar.append(")");
if (i < charKeys.length - 1) {
sbRegChar.append("|");
}
}
StringBuffer namesbRegChar = new StringBuffer(sbRegChar);
namesbRegChar.append(")(=|:|:)([\u4E00-\u9FA5\u00B7]{1,16})(;|,|\\||\\}|]|$)");
//由于(\\s*\\w+={0,2}) key:value 中value中结尾包括==(base64导致,所以修改该写法)
sbRegChar.append(")(=|:|:)(\\s*\\w+={0,2})(;|,|\\||\\}|]|$)");
namepatternChar = Pattern.compile(namesbRegChar.toString());// 编译正则表达式
patternChar = Pattern.compile(sbRegChar.toString());// 编译正则表达式
keys_length_char = charKeys.length;
}
}
public Log4jEncodeLayout(){
super();
init();
}
@Override
public String doLayout(ILoggingEvent event) {
String msg = super.doLayout(event);
return dimChar(msg); //对日志关键信息模糊配置* 如果没配置返回正常信息
}
/**
* 对银行卡以及身份证号脱敏处理
* 1.判断配置文件中是否已经配置需要脱敏字段
* 2.判断内容是否有需要脱敏的敏感信息
* 2.1 没有需要脱敏信息直接返回
* 3.判断敏感信息内容是否需要处理
* 3.1 处理银行卡和身份证敏感信息
* 3.2 处理用户姓名敏感信息
* @param @param msg
* @param @return
* @return String
* @throws
*/
private String dimChar(String msg) {
try{
//1.判断配置文件中是否已经配置需要脱敏字段
if(keys_length_char <= 0 || patternChar == null) {
return msg;
}
//2.判断内容是否有需要脱敏的敏感信息
boolean flag=false;
for (String key : charKeys) {
if(msg.contains(key)){
flag=true;
break;
}
}
//2.1 没有需要脱敏信息直接返回
if(!flag) {
return msg;
}
Matcher match = patternChar.matcher(msg);
boolean nameFlag = false;
// 处理要打印的日志信息
//3.判断敏感信息内容是否需要处理
StringBuffer sbMsg = new StringBuffer();
while (match.find()) {
//3.1 处理银行卡和身份证敏感信息
nameFlag = true;
// group(1)匹配key,group(keys_length+2)匹配(=|:|:),group(keys_length+3)匹配value,group(keys_length+4)匹配(;|,|\\||]|\\)|$)
match.appendReplacement(
sbMsg,
match.group(1)
+ match.group(keys_length_char + 2)
+ replaceChar(match.group(keys_length_char + 3))
+ match.group(keys_length_char + 4));
}
match.appendTail(sbMsg);// 增加最后一个匹配项后面的值
//3.2 处理用户姓名敏感信息
if(nameFlag) {
match = namepatternChar.matcher(sbMsg);
sbMsg = new StringBuffer();
}else{
match = namepatternChar.matcher(msg);
}
while (match.find()) {
nameFlag = true;
// group(1)匹配key,group(keys_length+2)匹配(=|:|:),group(keys_length+3)匹配value,group(keys_length+4)匹配(;|,|\\||]|\\)|$)
match.appendReplacement(
sbMsg,
match.group(1)
+ match.group(keys_length_char + 2)
+ replaceNameChar(match.group(keys_length_char + 3))
+ match.group(keys_length_char + 4));
}
match.appendTail(sbMsg);// 增加最后一个匹配项后面的值
return sbMsg.toString()+"\n";
}catch (Exception e) {
//如果跑出异常为了不影响流程,直接返回原信息
return msg;
}
}
/**
* 日志关键字用* 替换
* 规则: value <= 6 替换为******
* 6 > value <= 12 后四位保留,其他为*
* value > 12 前6位保留 中间* 后4位保留
* @param value
* @return
*/
private static String replaceChar(String value){
if(StringUtils.isEmpty(value)){
return "";
}
if(value.length() <= 6){ // value <= 6 替换为******
return lStr("",'*',value.length());
}else if(value.length() > 6 && value.length() <= 12){ //后四位保留,其他为*
int valLen = value.length();
String replaceHeadStr = value.substring(value.length() -4);
return replaceHeadStr = lStr(replaceHeadStr,'*',valLen);
}else if(value.length() > 12){ //前6位保留 中间* 后4位保留
String replaceHeadStr = value.substring(0,6);
String replaceTailStr = value.substring(value.length()-4);
String dimStr = lStr("",'*',value.length()-10);
return replaceHeadStr+dimStr+ replaceTailStr;
}else{
return value;
}
}
/**
* 日志姓名关键字替换
* 保留第一个汉字,后边用*号表示(例如:张三--》张*)
* @param @param value
* @param @return
* @return String
* @throws
*/
private static String replaceNameChar(String value){
if(StringUtils.isEmpty(value)){
return "";
}
String replaceHeadStr = value.substring(0,1);
return replaceHeadStr + lStr("",'*',value.length() - 1);
}
/*
* 左补长char
*/
public static String lStr(String s, char ch, int width) {
if (s.length() < width) { // 需要前面补'0'
while (s.length() < width)
s = ch + s;
} else { // 需要将高位丢弃
s = s.substring(s.length() - width, s.length());
}
return s;
}
}
本文链接:
/archives/1753545753563
版权声明:
本站所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自
刘同学的小站!
喜欢就支持一下吧