Как замаскировать номера кредитных карт в файлах журнала с Log4J?

Наше веб-приложение должно быть сделано совместимым 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 был замаскирован этим регистратором от случаев, когда он еще был сделан сервером бэкэнда, или кто бы ни
  • Я использую упрощенный regex, потому что я не волнуюсь по поводу ложных положительных сторон

Код является единицей, протестированной, таким образом, я справедливо убежден, что это работает правильно. Конечно, при определении возможности улучшить его сообщите мне :-)

28
задан Reddy 13 February 2012 в 10:05
поделиться

1 ответ

Вы можете написать свой собственный layout и настроить его для всех аппендеров...

У макета есть метод format, который делает String из loggingEvent, содержащего сообщение логирования...

15
ответ дан 28 November 2019 в 03:53
поделиться
Другие вопросы по тегам:

Похожие вопросы: