web-dev-qa-db-ja.com

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文字の長さは必要ありません。

特殊文字は次のとおりです。

`〜!@#$%^&*()_- + = []\| {};: '"。、/ <>?

17
Jason

その正規表現を適応させる最良の方法は、正規表現を取り出して、代わりにコードを書くことです。必要な正規表現は非常に長く複雑になるため、作成してから2時間後には読むことができません。同等のPHPコードは面倒ですが、少なくとも自分が書いたものを理解することができます。

ちなみに、これはあなたへのスラムを意味するものではありません。ほとんどの場合、正規表現はパスワード強度の検証にはほとんど適していませんが、要件は通常よりも複雑であり、それだけの価値はありません。また、あなたが投稿したその正規表現はがらくたです。 Web上に浮かんでいる正規表現を絶対に信用しないでください。または、そのことについては、任意のコード。または、一体、何でも。 :-/

31
Alan Moore

私はアランに同意する必要があります。既存の正規表現が非常に複雑な場合、なぜ1つの正規表現でそれを実行しようとするのでしょうか。

それを親しみやすい簡単なステップに分解するだけです。あなたはすでにそれをしました。

次に、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='/[!@#$%^&*()\-_=+{};:,<.>]/';  // 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;
}

誰も理解できない正規表現を書いて、一度にできるようにする必要があると人々が感じる理由は、私を超えています...


OK OK-本当に単一の正規表現が必要な場合は、ルールを検証するために lookaheads について学習してください。

このモンスターはあなたが一度に求めたことをします:

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

デモ

64
dawg

本当に正規表現を使用したい場合は、次のことを試してください。

(?=^(?:[^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]の2回の繰り返しをテストします。これは、大文字とそれに続く1つの大文字を除く0個以上の文字のシーケンスです。
  • (?=^(?:[^a-z]*[a-z]){2})(上記と同じ小文字で)
  • (?=^(?:\D*\d){2})(上記と同じ数字)
  • (?=^(?:\w*\W){2})(上記のWord以外の文字と同じですが、\Wを任意の特殊文字の文字クラスに変更できます)
  • ^[A-Za-z\d\W]{8,}$は、他のすべての文字クラスの和集合の文字のみで構成される文字列全体の長さをテストします。
16
Gumbo