Использование Positive LookAhead и LookBehind для маскировки пароля в строке подключения к базе данных - PullRequest
4 голосов
/ 19 сентября 2019

У меня в приложении VB.NET есть метод обработки исключений, который извлекает подробности из последнего возникшего исключения и отправляет эту информацию по электронной почте в нашу службу поддержки (я) для диагностики и устранения неполадок.Одним из возможных исключений является случай, когда приложение пытается подключиться или выполнить какой-либо SQL на одном из наших серверов баз данных.В этих случаях - особенно когда исключение происходит из-за сбоя подключения - я хочу увидеть строку подключения к базе данных, которая используется для проверки правильности ее форматирования.

Однако строки подключения к базе данных обычно содержат идентификатор пользователяи пароль, и я хочу замаскировать пароль в строке.Проблема, однако, заключается в том, что мы подключаемся к нескольким типам баз данных (например, PostgreSQL, MySQL, SQLite, MS Access и т. Д.) И, в зависимости от базы данных, в строке подключения может быть или не быть пароль.Кроме того, форматы строки подключения могут отличаться у разных поставщиков.

Я крайне незнаком с RegEx, но, используя https://regexr.com/,, мне удалось придуматьследующий шаблон RegEx, который, кажется, работает иногда :

(?<=;?[Pp][Aa][Ss][Ss].*=)(.*?)(?=;)|$

Пример строки подключения будет выглядеть следующим образом:

Host=SERVERNAME;Port=####;Database=DBNAME;Username=USERID;Password=MyPa$$Word;Integrated Security=False

Приведенный выше шаблон правильно соответствует MyPa$$Word в строке, если он явно в этом порядке, но если я переместу пару ключ / значение Password ближе к началу строки подключения, как показано ниже:

Host=SERVERNAME;Port=9999;Password=MyPa$$Word;Database=DBNAME;Username=USERID;Integrated Security=False

, затем оно соответствует MyPa$$Word, DBNAME, и USERID.Если переместить его в конец строки:

Host=SERVERNAME;Port=9999;Database=DBNAME;Username=USERID;Integrated Security=False;Password=MyPa$$Word

, шаблон не найдет каких-либо совпадений.Просто чтобы убедиться, что ключ / значение с пробелом (Integrated Security=False) не перепутали шаблон, я удалил его из строки и получил те же результаты.

Поскольку строка подключения может быть структурирована в видеразличные способы, в зависимости от типа базы данных, пользовательского ввода и т. д., я хотел бы иметь возможность использовать RegEx, чтобы найти (без учета регистра) пару ключ / значение пароля в любом месте строки подключения, извлечь только действительный парользначение, и заменить его чем-то (например, [HIDDEN]).Я знаю, что мог бы просто сделать String.Split(Convert.ToChar(";")) для всей строки подключения и проверить каждую пару ключ / значение, но я бы предпочел сделать это с RegEx, если это возможно.

Ответы [ 2 ]

3 голосов
/ 19 сентября 2019

Примерно так может сработать:

((^|;)Password=)(.*?)(;|$)

Пароль будет в $3, поэтому просто не указывайте эту группу захвата при выполнении замены.

Нажмите «Код»Генератор "в левой части этой страницы, чтобы увидеть его в действии в PHP.

https://regex101.com/r/gxztmy/1

1 голос
/ 19 сентября 2019

В VB.NET вы можете рассмотреть варианты

text = Regex.Replace(text, "(?<=(?<![^;])pass\w*=).*?(?=;[\w\s]+=|$)", "[HIDDEN]", RegexOptions.IgnoreCase)

или

text = Regex.Replace(text, "(?<![^;])(pass\w*=).*?(?=;[\w\s]+=|$)", "$1[HIDDEN]", RegexOptions.IgnoreCase)

C # на случай, если это понадобится:

text = Regex.Replace(text, @"(?<=(?<![^;])pass\w*=).*?(?=;[\w\s]+=|$)", "[HIDDEN]", RegexOptions.IgnoreCase);
text = Regex.Replace(text, @"(?<![^;])(pass\w*=).*?(?=;[\w\s]+=|$)", "$1[HIDDEN]", RegexOptions.IgnoreCase);

См. Демонстрационный пример регулярных выражений и демонстрационный пример решения для группы захвата .

Подробности

  • (?i) - модификатор без учета регистра (или RegexOptions.IgnoreCase)
  • (?<=(?<![^;])pass\w*=) - положительный взгляд сзади, для которого требуется строка pass (с предшествующим , или началом позиции строки) + любое 0 или более словсимволы с последующим = непосредственно слева от текущего местоположения
  • .*? - любые 0+ символов, кроме символа LF, должны быть как можно меньше
  • (?=;[\w\s]+=|$) - позиция вза строкой сразу следуют ;, 1+ слово или пробельные символы и = или конец строки.

В решении с группой захвата захваченная подстрока помещается обратно в результат, используя $1 заполнитель.

Почему (?<![^;]), а не (?<=^|;)?Потому что чередование незанятого внешнего вида дорого обходится с точки зрения производительности.Имеет смысл минимизировать накладные расходы, если существует эквивалентный шаблон без чередования.(?<![^;]) соответствует любому расположению, которое находится либо в начале строки, либо перед ;, поэтому оно должно быть предпочтительным.Этот тип шаблона невозможен, если левый контекст представляет собой строку из нескольких символов или если требуется многострочный режим.

...