logback日志之脱敏处理
对于项目日志脱敏,大家肯定都不陌生,现在对于信息安全越来越重视,在日志中直接打印手机号,身份证号等私人信息和容易造成个人信息的泄露,所以几乎所有的公司都会要求日志中敏感信息的处理,本人也是因为公司安全部门检查,因为部分日志输出了敏感信息,需要对项目日志进行改造,但是问题是如果我们挨个去排查那个日志有输出敏感信息的话,那工作量无疑是巨大的,那有没有一种方式进行全局处理呢,答案是肯定的,因为公司使用的slf4j+logback,就以此为例给出解决方案。因为只是个小技术工具,所以直接上代码:
logback.xml配置文件修改
<springProperty scope="context" name="log.consolePattern" source="hcf.log.console-pattern"
defaultValue="%red(%d{yyyy-MM-dd HH:mm:ss.SSS})|%highlight(%level)|%green(%thread)|%X{clientIp}|%X{traceId}|%X{rpcId}|%boldMagenta(%c.%M[%L])|%cyan(%msg%n)"/>
<conversionRule conversionWord="msg" converterClass="com.credithc.channel.common.util.SensitiveConverter"> </conversionRule>
注意:
-
conversionRule标签必须紧挨着configuration标签写,绝对不可以放在appender标签下面,但是可以放在springProperty下面
-
conversionRule标签中的converterClass属性指向的是我们自定义的处理敏感信息的类,conversionWord的值对应的是我们定义的日志格式中的日志内容的占位符,也就是上面代码中%msg去掉%的部分
自定义脱敏处理类
package com.credithc.openapi.flowplatform.util; import ch.qos.logback.classic.pattern.MessageConverter; import ch.qos.logback.classic.spi.ILoggingEvent; import org.apache.commons.lang3.StringUtils; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * 日志脱敏过滤器 * * @author 邝翔 */ public class SensitiveConverterUtil extends MessageConverter { private static final String PHONE_REGEX = "(\\+861[3|4|5|7|8][0-9]\\d{8}[^\\d])|(^1[3|4|5|7|8][0-9]\\d{8})[^\\d]|([^\\d]1[3|4|5|7|8][0-9]\\d{8}[^\\d])"; private static final String IDCARD_REGEX = "[^\\d]([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])[^\\d]|[^\\d](^[1-9]\\d{5}\\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\\d{3})[^\\d]"; private static final String KEY = "axedfqLGpu"; @Override public String convert(ILoggingEvent event) { // 获取原始日志 String requestLogMsg = event.getFormattedMessage(); // 获取返回脱敏后的日志 return filterSensitive(requestLogMsg); } /** * 对敏感信息脱敏 */ private static String filterSensitive(String content) { try { if (StringUtils.isBlank(content)) { return content; } content = filterIdcard(content); content = filterMobile(content); return content; } catch (Exception e) { return content; } } /** * 身份证号脱敏 */ private static String filterIdcard(String num) { Pattern pattern = Pattern.compile(IDCARD_REGEX); Matcher matcher = pattern.matcher(num); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, baseSensitive(matcher.group(), 4, 4)); } matcher.appendTail(sb); return sb.toString(); } /** * 手机号码脱敏 */ private static String filterMobile(String num) { Pattern pattern = Pattern.compile(PHONE_REGEX); Matcher matcher = pattern.matcher(num); StringBuffer sb = new StringBuffer(); while (matcher.find()) { matcher.appendReplacement(sb, baseSensitive(matcher.group(), 3, 4)); } matcher.appendTail(sb); return sb.toString(); } /** * 基础脱敏处理 指定起止展示长度 剩余用"KEY"中字符替换 * * @param str 待脱敏的字符串 * @param startLength 开始展示长度 * @param endLength 末尾展示长度 * @return 脱敏后的字符串 */ private static String baseSensitive(String str, int startLength, int endLength) { if (StringUtils.isBlank(str)) { return ""; } String replacement = str.substring(startLength, str.length() - endLength); StringBuilder sb = new StringBuilder(); for (int i = 0; i < replacement.length(); i++) { char ch; if (replacement.charAt(i) >= '0' && replacement.charAt(i) <= '9') { ch = KEY.charAt(replacement.charAt(i) - '0'); } else { 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"中字符解密 */ private static String decrypt(String str, int startLength, int endLength) { if (StringUtils.isBlank(str)) { return ""; } String replacement = str.substring(startLength, str.length() - endLength); StringBuilder sb = new StringBuilder(); for (int i = 0; i < replacement.length(); i++) { int index = KEY.indexOf(replacement.charAt(i)); if (index != -1) { sb.append(index); } else { sb.append(replacement.charAt(i)); } } return StringUtils.left(str, startLength).concat(StringUtils.leftPad(StringUtils.right(str, endLength), str.length() - startLength, sb.toString())); } }