微服务-日志脱敏
微服务-日志脱敏
场景
在很多情况下,都需要对我们输出的数据进行脱敏,比如
- 日志脱敏
- 数据库数据脱敏
这里我们实现日志脱敏
目标
- 减少对代码的入侵
- 可扩展性
logback 中实现日志脱敏
- 自定义 encoder: SensitivePatternLayoutEncoder
- 自定义 PatternLayout: SensitivePatternLayout
SensitivePatternLayoutEncoder
public class SensitivePatternLayoutEncoder extends PatternLayoutEncoderBase<ILoggingEvent> {@Overridepublic void start() {PatternLayout patternLayout = new SensitivePatternLayout();patternLayout.setContext(context);patternLayout.setPattern(getPattern());patternLayout.setOutputPatternAsHeader(outputPatternAsHeader);patternLayout.start();this.layout = patternLayout;super.start();}}
SensitivePatternLayout
public class SensitivePatternLayout extends PatternLayout {private static List<SensitiveStrategy> patterns = new ArrayList<>();private volatile boolean init = false;@Overridepublic String doLayout(ILoggingEvent event) {String message = super.doLayout(event);if (!init){init = true;//添加默认策略addDefaultPatterns();}if (patterns != null) {for (SensitiveStrategy sensitiveStrategy : patterns) {Matcher matcher = sensitiveStrategy.pattern().matcher(message);StringBuffer sb = new StringBuffer();while (matcher.find()) {String group = matcher.group(0);matcher.appendReplacement(sb, sensitiveStrategy.resolve(group));}matcher.appendTail(sb);message = sb.toString();}}return message;}/*** 默认规则*/private void addDefaultPatterns() {addPattern(new EmailSensitiveStrategy());}/*** 向后添加规则* @param sensitiveStrategy*/public static void addPattern(SensitiveStrategy sensitiveStrategy) {patterns.add(sensitiveStrategy);}/*** 向前添加规则,优先级越高* @param sensitiveStrategy*/public static void addFirstPattern(SensitiveStrategy sensitiveStrategy) {patterns.add(0,sensitiveStrategy);}
}
实现匹配策略
定义策略接口:
public interface SensitiveStrategy { /** * 匹配正则 * @return */ Pattern pattern(); /** * 处理匹配之后结果 * @param message 匹配出来的字符 * @return */ String resolve(String message);
}
EmailSensitiveStrategy
匹配邮箱
public class EmailSensitiveStrategy implements SensitiveStrategy{@Overridepublic Pattern pattern() {//匹配email的正则表达式return Pattern.compile("\\b([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\\.[a-zA-Z0-9_-]{2,3}){1,2})\\b");}@Overridepublic String resolve(String message) {return DesensitizedUtil.email(message);}
}
PhoneSensitiveStrategy
匹配手机号
public class PhoneSensitiveStrategy implements SensitiveStrategy{@Overridepublic Pattern pattern() {//匹配手机号正则return Pattern.compile("\\b1[3-9]\\d{9}\\b");}@Overridepublic String resolve(String message) {return DesensitizedUtil.mobilePhone(message);}
}
logback.xml配置
使用自定义的 encoder
<configuration> <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> <encoder class="com.x.x.mvc.log.SensitivePatternLayoutEncoder"> <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder>
</appender> <root level="debug"> <appender-ref ref="STDOUT"/>
</root> </configuration>
测试
@Slf4j
public class LogMain {static {//这里可以在项目中独自添加实现//配置手机号SensitivePatternLayout.addFirstPattern(new PhoneSensitiveStrategy());}public static void main(String[] args) throws JoranException {log.debug("User 13767568987 accessed account with ID 1313132@qq.com and other email 37489339@gmail.com");}}
结果:
DEBUG com.LogMain - User 137****8987 accessed account with ID 1******@qq.com and other email 3*******@gmail.com
good luck!
