2010-04-14 2 views
17

Я видел следующее регулярное выражение в Интернете.Регулярное выражение PHP для надежной проверки пароля

(?=^.{8,}$)((?=.*\d)|(?=.*\W+))(?![.\n])(?=.*[A-Z])(?=.*[a-z]).*$ 

Он проверяет только если строка:

* contain at least (1) upper case letter 
    * contain at least (1) lower case letter 
    * contain at least (1) number or special character 
    * contain at least (8) characters in length 

Я хотел бы знать, как преобразовать это регулярное выражение, так что он проверяет строку

* contain at least (2) upper case letter 
* contain at least (2) lower case letter 
* contain at least (2) digits 
* contain at least (2) special character 
* contain at least (8) characters in length 

Ну, если он содержит по крайней мере 2 верхних, нижних, цифр и специальных символов, тогда я бы не нуждался в 8-значной длине.

Специальные символы включают в себя:.?

`~ @ # $%^& *() _- + = [] \ | {} ;: '»,/<>

+2

Уточнитните * специальный символ *. Вы имеете в виду только: '! @ # $%^& *() -_ = + [{]} ;: '", <.> /? 'Или что-то еще? – Crozin

+0

обновил вопрос с помощью кодировки специальных символов – Jason

+4

Don «Вы ненавидите те веб-сайты, которые ограничивают сложность пароля» по соображениям безопасности »? Вы хотите установить« .evmhcfcyK »(легко запомнить, потому что это исходит из предложения), и вы получаете« abcd1234 », написанный в post-it note: –

ответ

31

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

Это, кстати, не означает, как удар. В большинстве случаев регулярные выражения редко подходят для проверки надежности паролей, но ваши требования более сложны, чем обычно, и это просто не стоит. Кроме того, это регулярное выражение, которое вы разместили, - дерьмо. Никогда не доверяйте регулярным выражениям, которые вы находите в Интернете. Или любой код, если на то пошло. Или, heck, ничего. : -/

+3

Я согласен, что лучше всего запускать отдельные проверки не с одним волшебным регулярным выражением. Таким образом, вы можете легко модифицировать определенные части или добавлять/удалять их. Лично я не думаю, что принудительный сильный пароль - это хороший пользовательский интерфейс, эти JS-based «Пределы прочности пароля» намного лучше, потому что вы оба обучаете пользователя и мягко наказываете их за использование плохого пароля, но если они действительно хотят его использовать, они могут. – TravisO

+0

ok ok .. вы все убеждаете меня .. I не будет проверять регулярное выражение, так как оно явно не читается. е! – Jason

+0

@TravisO: Да, мне нравятся эти бары для защиты паролем. –

16

Если вы действительно хотите использовать регулярные выражения, попробуйте следующее:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$ 

Некоторые объяснения:

  • (?=^(?:[^A-Z]*[A-Z]){2}) тесты для двух повторений [^A-Z]*[A-Z], который представляет собой последовательность из нуля или больше символов, кроме заглавных букв, за которыми следует одна прописная буква
  • (?=^(?:[^a-z]*[a-z]){2}) (то же, что указано выше с прописными буквами)
  • (?=^(?:\D*\d){2}) (такой же, как и выше с цифрами)
  • (?=^(?:\w*\W){2}) (так же, как выше, с символами, не слово, но вы можете изменить \W с классом персонажа из любой специальных символов, которые вы хотите)
  • ^[A-Za-z\d\W]{8,}$ проверяет длину целого строка, состоящая только из характера объединения всех других классов символов.
+0

Отличный ответ с хорошим объяснением, я голосую за это, хотя я не рекомендую ваш ответ. В этом случае я думаю, что он становится нечитаемым, стандартный код будет лучшим выбором, единственной причиной, по которой я буду использовать регулярное выражение, потому что экстремальная производительность была проблемой, и мне нужно было проверить миллионы паролей. – TravisO

+1

На самом деле, если производительность была фактором, было бы еще одной причиной * не * использовать регулярное выражение. В противном случае я согласен: +1 для окончательного решения регулярного выражения (если вам действительно нужно идти по этому маршруту). –

+0

+1 Но вместо того, чтобы предоставлять одно длинное нечитаемое регулярное выражение в собственном формате (и отдельное объяснение), намного лучше (и меньше работать) писать регулярное выражение в режиме свободного пробега из get-go с полным отступом и щедрые комментарии. Дополнительным преимуществом является то, что расширенное самодокументируемое регулярное выражение режима свободного пробега в будущем будет более удобным в обслуживании. – ridgerunner

62

Я должен согласиться с Аланом. Если существующее регулярное выражение так сложно, зачем пытаться сделать это только в одном регулярном выражении?

Просто откройте его в простых простых шагах. Вы уже это сделали.

Теперь напишите 4 регулярных выражения, чтобы проверить свои части, добавить основную логику в 4 регулярное выражение и измерить длину строки. Готово.

Какой бы вы предпочли отладки, это:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$ (который не работает кстати ...)

или это:

function valid_pass($candidate) { 
    $r1='/[A-Z]/'; //Uppercase 
    $r2='/[a-z]/'; //lowercase 
    $r3='/[[email protected]#$%^&*()\-_=+{};:,<.>]/'; // whatever you mean by 'special char' 
    $r4='/[0-9]/'; //numbers 

    if(preg_match_all($r1,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r2,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r3,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r4,$candidate, $o)<2) return FALSE; 

    if(strlen($candidate)<8) return FALSE; 

    return TRUE; 
} 

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


Хорошо, если вы действительно хотите использовать одно регулярное выражение, узнайте о lookaheads, чтобы проверить свои правила.

Этот монстр делает то, что вы просили в одном дыхании:

^          # start of line 
(?=(?:.*[A-Z]){2,})      # 2 upper case letters 
(?=(?:.*[a-z]){2,})      # 2 lower case letters 
(?=(?:.*\d){2,})       # 2 digits 
(?=(?:.*[[email protected]#$%^&*()\-_=+{};:,<.>]){2,}) # 2 special characters 
(.{8,})         # length 8 or more 
$          # EOL 

Demo

+0

Мне нравится это решение; хорошо и ясно, что происходит, будучи достаточно краткими. +1 – andrhamm

+0

@andrhamm Есть ли способ подключения первых двух строк? Верхний или нижний символы не верхний и нижний? – Byakugan

+0

@Byakugan try $ r1 = '/ [A-Za-z] /'; // Верхний или нижний регистр – andrhamm

Смежные вопросы