Подтвердить что ты не робот

Регулярное выражение 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 символов.

Специальные символы:

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

Ответ 1

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

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

Ответ 2

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

Просто сложите его на простые шаги. Вы уже это сделали.

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

Что вы предпочитаете отлаживать, это:

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

или это:

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 

Демо

Ответ 3

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

(?=^(?:[^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,}$ проверяет длину всей строки, состоящей только из символа объединения всех других классов символов.