Наше веб-приложение должно быть сделано совместимым PCI, т.е. это не должно хранить номера кредитных карт. Приложение является frontend к мейнфреймовой системе, которая обрабатывает числа CC внутренне и - как мы только что узнали - иногда все еще выкладывает полное число CC на одном из его экранов ответа. По умолчанию, целый контент этих ответов зарегистрированы на уровне отладки, и также содержание, проанализированное от них, может быть зарегистрировано много различных мест. Таким образом, я не могу выследить источник таких утечек данных. Я должен удостовериться, что числа CC маскируются в наших файлах журнала.
regex часть не является проблемой, я снова использую regex, который мы уже используем в нескольких других местах. Однако я просто не могу найти хороший источник о том, как изменить часть сообщения журнала с Log4J. Фильтры, кажется, намного более ограничены, только в состоянии решить, зарегистрировать ли конкретное событие или нет, но не могут изменить содержание сообщения. Я также нашел обертку безопасности ESAPI API для Log4J, который на первый взгляд обещает сделать то, что я хочу. Однако, по-видимому, я должен был бы заменить все регистраторы в коде с классом регистратора 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 был замаскирован этим регистратором от случаев, когда он еще был сделан сервером бэкэнда, или кто бы ниКод является единицей, протестированной, таким образом, я справедливо убежден, что это работает правильно. Конечно, при определении возможности улучшить его сообщите мне :-)
Вы можете написать свой собственный layout и настроить его для всех аппендеров...
У макета есть метод format, который делает String из loggingEvent, содержащего сообщение логирования...