我们的网络应用需要符合PCI标准,即不得存储任何信用卡号码。该应用程序是大型机系统的前端,它在内部处理CC号码 - 正如我们刚刚发现的那样 - 偶尔会在其响应屏幕上吐出一个完整的CC号码。默认情况下,这些响应的全部内容都以调试级别记录,并且从这些响应中解析的内容也可以记录在许多不同的位置。所以我无法追捕这些数据泄漏的来源。我必须确保在我们的日志文件中屏蔽了CC编号。
正则表达式部分不是问题,我将重用我们已经在其他几个地方使用的正则表达式。但是我找不到有关如何使用Log4J更改日志消息的一部分的任何好的来源。过滤器似乎更受限制,只能决定是否记录特定事件,但不能改变消息的内容。我还发现Log4J的ESAPI security wrapper API乍一看有望做我想做的事。但是,显然我需要用ESAPI记录器类替换代码中的所有记录器 - 这是一个痛苦的屁股。我希望有一个更透明的解决方案。
知道如何屏蔽Log4J输出中的信用卡号码吗?
更新:根据@ pgras最初的想法,这是一个有效的解决方案:
public class CardNumberFilteringLayout extends PatternLayout {
private static final String MASK = "$1++++++++++++";
private static final Pattern PATTERN = Pattern.compile("([0-9]{4})([0-9]{9,15})");
@Override
public String format(LoggingEvent event) {
if (event.getMessage() instanceof String) {
String message = event.getRenderedMessage();
Matcher matcher = PATTERN.matcher(message);
if (matcher.find()) {
String maskedMessage = matcher.replaceAll(MASK);
@SuppressWarnings({ "ThrowableResultOfMethodCallIgnored" })
Throwable throwable = event.getThrowableInformation() != null ?
event.getThrowableInformation().getThrowable() : null;
LoggingEvent maskedEvent = new LoggingEvent(event.fqnOfCategoryClass,
Logger.getLogger(event.getLoggerName()), event.timeStamp,
event.getLevel(), maskedMessage, throwable);
return super.format(maskedEvent);
}
}
return super.format(event);
}
}
注意:
+
而不是*
进行掩码,因为我想区分CID被此记录器屏蔽的情况,以及后端服务器完成的情况,或者其他人< / LI>
代码经过单元测试,所以我相信它能正常工作。当然,如果您发现任何改进它的可能性,请告诉我: - )
答案 0 :(得分:15)
你可以编写自己的layout并为所有appender配置它......
Layout有一个格式方法,它从包含日志消息的loggingEvent生成一个String ...
答案 1 :(得分:5)
更好地实施信用卡号码屏蔽是http://adamcaudill.com/2011/10/20/masking-credit-cards-for-pci/。 您希望记录发行者和校验和,但不记录PAN(主帐号)。