Java 如何使用 Log4J 在日志文件中屏蔽信用卡号?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2461726/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to mask credit card numbers in log files with Log4J?
提问by Péter T?r?k
Our web app needs to be made PCI compliant, i.e. it must not store any credit card numbers. The app is a frontend to a mainframe system which handles the CC numbers internally and - as we have just found out - occasionally still spits out a full CC number on one of its response screens. By default, the whole content of these responses are logged at debug level, and also the content parsed from these can be logged in lots of different places. So I can't hunt down the source of such data leaks. I must make sure that CC numbers are masked in our log files.
我们的 Web 应用程序需要符合 PCI 标准,即不得存储任何信用卡号。该应用程序是大型机系统的前端,该系统在内部处理 CC 编号,并且 - 正如我们刚刚发现的那样 - 偶尔仍会在其响应屏幕之一上显示完整的 CC 编号。默认情况下,这些响应的全部内容都记录在调试级别,并且从这些响应中解析出来的内容可以记录在许多不同的地方。所以我无法追查此类数据泄露的来源。我必须确保在我们的日志文件中屏蔽了 CC 编号。
The regex part is not an issue, I will reuse the regex we already use in several other places. However I just can't find any good source on how to alter a part of a log message with Log4J. Filters seem to be much more limited, only able to decide whether to log a particular event or not, but can't alter the content of the message. I also found the ESAPI security wrapper APIfor Log4J which at first sight promises to do what I want. However, apparently I would need to replace all the loggers in the code with the ESAPI logger class - a pain in the butt. I would prefer a more transparent solution.
正则表达式部分不是问题,我将重用我们已经在其他几个地方使用的正则表达式。但是,我找不到任何关于如何使用 Log4J 更改日志消息的一部分的好的来源。过滤器似乎受到更多限制,只能决定是否记录特定事件,但不能更改消息的内容。我还发现了用于 Log4J的ESAPI 安全包装器 API,乍一看,它可以满足我的要求。但是,显然我需要用 ESAPI 记录器类替换代码中的所有记录器 - 很麻烦。我更喜欢更透明的解决方案。
Any idea how to mask out credit card numbers from Log4J output?
知道如何从 Log4J 输出中屏蔽信用卡号吗?
Update:Based on @pgras's original idea, here is a working solution:
更新:基于@pgras 的原始想法,这是一个可行的解决方案:
public class CardNumberFilteringLayout extends PatternLayout {
private static final String MASK = "++++++++++++";
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);
}
}
Notes:
笔记:
- I mask with
+
rather than*
, because I want to tell apart cases when the CID was masked by this logger, from cases when it was done by the backend server, or whoever else - I use a simplistic regex because I am not worried about false positives
- 我用
+
而不是屏蔽*
,因为我想区分 CID 被此记录器屏蔽的情况,后端服务器完成的情况,或其他任何人 - 我使用简单的正则表达式,因为我不担心误报
The code is unit tested so I am fairly convinced it works properly. Of course, if you spot any possibility to improve it, please let me know :-)
代码经过单元测试,所以我相当确信它可以正常工作。当然,如果您发现任何改进它的可能性,请告诉我:-)
采纳答案by pgras
回答by Concrete Gannet
A better implementation of credit card number masking is at http://adamcaudill.com/2011/10/20/masking-credit-cards-for-pci/. You want to log the issuer and the checksum, but not the PAN (Primary Account Number).
信用卡号屏蔽的更好实现位于http://adamcaudill.com/2011/10/20/masking-credit-cards-for-pci/。您想记录发行者和校验和,而不是 PAN(主帐号)。