PHP Regex для человеческих имен - PullRequest
9 голосов
/ 11 августа 2009

У меня возникла небольшая проблема с Regex, который я использую для имен людей.

$rexName = '/^[a-z' -]$/i';

Предположим, пользователь с именем Юрген хочет зарегистрироваться? Или Боб? Это довольно распространенное явление в Европе. Для этого есть специальная запись?

РЕДАКТИРОВАТЬ: просто бросил имя Юргена против создателя регулярных выражений, и оно разбивает слово на букву ü ...

http://www.txt2re.com/index.php3?s=J%FCrgen+Blalock&submit=Show+Matches

РЕДАКТИРОВАТЬ2: Хорошо, поскольку проверка таких конкретных вещей является сложной задачей, почему бы не использовать регулярное выражение, которое просто проверяет наличие недопустимых символов?

$rexSafety = "/^[^<,\"@/{}()*$%?=>:|;#]*$/i";

(какие из них можно использовать при любой попытке взлома?)

Например. Это позволяет 'и - знаки, но вам нужно; чтобы он работал в SQL, и они будут остановлены. Какие-нибудь другие символы, которые обычно используются для внедрения SQL-атак SQL, которые мне не хватает?

Ответы [ 4 ]

21 голосов
/ 11 августа 2009

Я бы действительно сказал: не пытайтесь проверять имена: в тот или иной день ваш код встретится с именем, которое он считает «неправильным» ... И как вы думаете, как бы вы отреагировали, когда приложение скажет ему? " ваше имя недействительно "?

В зависимости от того, чего вы действительно хотите достичь, вы можете рассмотреть возможность использования какого-либо черного списка / фильтров, чтобы исключить «неназванные» имена, о которых вы думали: возможно, они позволят некоторым «плохим именам» пройти, но при по крайней мере, это не должно препятствовать доступу существующего имени к вашему приложению.

Вот несколько примеров правил, которые приходят на ум:

  • без номера
  • без специальных символов, как "~{()}@^$%?;:/*§£ø и, возможно, некоторые другие
  • не более 3 пробелов?
  • ни один из "admin", "support", "moderator", "test" и некоторые другие очевидные не-имена, которые люди склонны использовать, когда они не хотят вводить свое настоящее имя ...
    • (но, если они не хотят давать вам свое имя, их все равно не будет, даже если вы запретите им вводить несколько случайных букв, они могут просто использовать настоящее имя ... Которое не принадлежит им)

Да, это не идеально; и да, он пропустит некоторые неназванные имена ... Но для вашего приложения это, вероятно, намного лучше, чем сказать кому-то "ваше имя неверно" (да, я настаиваю ^^)


И, чтобы ответить на комментарий вы оставили под другим ответом:

Я мог бы просто запретить самой команде символы для SQL-инъекции и XSS атаки,

О SQL Injection, вы должны экранировать свои данные перед отправкой в ​​базу данных; и, если вы всегда избегаете этих данных (вы должны!), вам не нужно заботиться о том, что пользователи могут вводить или нет: поскольку они экранированы, вы всегда рискуете.

То же самое в XSS: поскольку вы всегда избегаете своих данных при выводе их (вы должны!), Нет риска инъекции; -)


РЕДАКТИРОВАТЬ: если вы просто используете это регулярное выражение, это не будет работать очень хорошо:

следующий код:

$rexSafety = "/^[^<,\"@/{}()*$%?=>:|;#]*$/i";
if (preg_match($rexSafety, 'martin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

Получит вам хотя бы предупреждение:

Warning: preg_match() [function.preg-match]: Unknown modifier '{'

Вы должны убежать хотя бы от некоторых из этих специальных символов; Я позволю вам покопаться в шаблонах PCRE для получения дополнительной информации (действительно есть много информации о PCRE / regex; и я не смогу объяснить все это)

Если вы действительно хотите проверить, что ни один из этих символов не находится внутри заданного фрагмента данных, вы можете получить что-то вроде этого:

$rexSafety = "/[\^<,\"@\/\{\}\(\)\*\$%\?=>:\|;#]+/i";
if (preg_match($rexSafety, 'martin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

(Это быстрое и грязное предложение, которое нужно усовершенствовать!)

Этот говорит "ОК" (ну, я определенно надеюсь, что с моим собственным именем все в порядке!)
И тот же пример с некоторыми специальными символами, например:

$rexSafety = "/[\^<,\"@\/\{\}\(\)\*\$%\?=>:\|;#]+/i";
if (preg_match($rexSafety, 'ma{rtin')) {
    var_dump('bad name');
} else {
    var_dump('ok');
}

скажет "плохое имя"

Но обратите внимание, я не полностью проверил это, и, вероятно, требуется больше работы! Не используйте это на своем сайте, если вы не проверили это очень тщательно!


Также обратите внимание, что одиночная кавычка может быть полезна при попытке сделать SQL-инъекцию ... Но это, вероятно, символ, допустимый в некоторых именах ... Так что простого исключения некоторых символов может быть недостаточно; -)

6 голосов
/ 11 августа 2009

Реализация PHP PCRE поддерживает Свойства символов Unicode , которые охватывают больший набор символов. Таким образом, вы можете использовать комбинацию \p{L} (буквенные символы), \p{P} (знаки пунктуации) и \p{Zs} (символы пробела):

/^[\p{L}\p{P}\p{Zs}]+$/

Но могут быть персонажи, которые не охватываются этими категориями персонажей, в то время как могут быть некоторые включенные, которые вы не хотите допускать.

Поэтому я советую вам не использовать регулярные выражения для данных с таким неопределенным диапазоном значений, как имя реального человека.


Редактировать Когда вы отредактировали свой вопрос и теперь видите, что вы просто хотите предотвратить некоторые атаки с использованием кода: лучше избегать этих символов, а не отвергать их как потенциальную попытку атаки.

Используйте mysql_real_escape_string или подготовленные операторы для запросов SQL, htmlspecialchars для вывода HTML и другие соответствующие функции для других языков.

4 голосов
/ 11 августа 2009

Это проблема без простого общего решения. Дело в том, что вы действительно не можете предсказать, какие символы может содержать имя. Вероятно, лучшее решение - определить маску отрицательных символов, чтобы исключить некоторые специальные символы, которые вы действительно не хотите использовать в имени.

Вы можете сделать это, используя:

$ regexp = "/ ^ [ ^ <поставить нежелательные символы здесь> ] + $ /

2 голосов
/ 01 ноября 2009

Если вы пытаетесь разобрать человеческое имя в PHP, я рекомендую сценарий Кита Бекмана nameparse.php .

...