2010-04-14 9 views
17

Ich habe den folgenden regulären Ausdruck im Internet gesehen.PHP regulären Ausdruck für starke Passwort-Validierung

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

Es bestätigt nur, wenn die Zeichenfolge:

* 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 

Ich mag gerne wissen, wie Sie diesen regulären Ausdruck zu konvertieren, so dass es die Zeichenfolge

* 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 

Nun prüft, ob es enthält mindestens 2 obere, untere, Ziffern und Sonderzeichen, dann würde ich nicht die Länge von 8 Zeichen benötigen.

Sonderzeichen enthalten:.?

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

+2

Bitte definieren * Sonderzeichen *. Meinst du nur: '! @ # $%^& *() -_ = + [{]}; '", <.> /? 'Oder vielleicht noch etwas? – Crozin

+0

aktualisierte die Frage mit dem Zeichensatz der Sonderzeichen – Jason

+4

Don hasst du diese Websites, die die Passwortkomplexität aus Sicherheitsgründen einschränken? Du willst ".evmhcfcyK" setzen (leicht zu merken, weil es aus einem Satz kommt) und am Ende mit "abcd1234" in einem Post-it schreiben Hinweis: –

Antwort

31

Der beste Weg, um diese Regex anzupassen, ist es, es auszupacken und schreiben Sie stattdessen Code Die erforderliche Regex wäre so lang und kompliziert, Sie könnten es nicht lesen zwei Stunden, nachdem Sie es geschrieben haben wird langweilig sein, aber zumindest wirst du verstehen, was du geschrieben hast.

Das ist übrigens nicht als Slam für dich gedacht. Regexes sind in den meisten Fällen kaum für die Validierung der Passwortstärke geeignet, aber Ihre Anforderungen sind komplizierter als üblich und es lohnt sich einfach nicht. Außerdem ist diese von Ihnen gepostete Regex Mist. Traue niemals Regexes, die du im Internet findest. Oder irgendein Code, für diese Angelegenheit. Oder, hack, alles. : -/

+3

Ich stimme zu, es ist am besten, separate Kontrollen nicht eine magische Regex zu laufen. Auf diese Weise können Sie leicht bestimmte Teile ändern oder hinzufügen/entfernen. Persönlich glaube ich nicht, ein starkes Passwort zu zwingen ist eine gute Benutzererfahrung, diese JS basiert "Passwortstärke" -Balken sind viel besser, weil Sie sowohl den Benutzer erziehen als auch milde bestrafen, wenn sie ein schlechtes Passwort verwenden, aber wenn sie wirklich eines verwenden wollen, können sie das. – TravisO

+0

ok ok .. Sie alle überzeugen mich .. Ich Ich werde die Regex nicht ausprobieren, da sie eindeutig nicht lesbar ist e! – Jason

+0

@TravisO: Ja, ich mag diese Passwort-Stärke-Balken auch. –

16

Wenn Sie wirklich einen regulären Ausdruck verwenden möchten, versuchen Sie dies:

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

eine Erklärung:

  • (?=^(?:[^A-Z]*[A-Z]){2}) Tests für zwei Wiederholungen von [^A-Z]*[A-Z], die eine Folge von Null ist oder mehr Zeichen außer Großbuchstaben gefolgt von einem Großbuchstaben
  • (?=^(?:[^a-z]*[a-z]){2}) (wie oben mit Kleinbuchstaben)
  • (?=^(?:\D*\d){2}) (wie oben mit Ziffern)
  • (?=^(?:\w*\W){2}) (wie oben mit Nicht-Wort-Zeichen, aber Sie können \W mit einer Zeichenklasse von was auch immer Sonderzeichen Sie wollen ändern)
  • ^[A-Za-z\d\W]{8,}$ die Länge des gesamten Tests Zeichenkette, die nur aus Zeichen der Vereinigung aller anderen Zeichenklassen besteht.
+0

Große Antwort mit einer netten Erklärung, ich stimme dies, obwohl ich Ihre Antwort nicht empfehle. In diesem Fall denke ich, dass es unlesbar wird, Standard-Code wäre eine bessere Wahl, der einzige Grund, warum ich Regex verwenden würde, weil extreme Leistung ein Problem war und ich Millionen von Passwörtern überprüfen musste. – TravisO

+1

Eigentlich, wenn die Leistung ein Faktor wäre, wäre es ein anderer Grund * nicht * eine Regex zu verwenden. Ansonsten stimme ich zu: +1 für die definitive Regex-Lösung (für den Fall, dass Sie diese Route wirklich gehen müssen). –

+0

+1 Aber anstatt eine lange unlesbare Regex im nativen Format (und eine separate Erklärung) bereitzustellen, ist es viel besser (und weniger Arbeit), die Regex von Anfang an im freien Beabstandungsmodus zu schreiben, komplett mit richtigem Einzug und großzügige Kommentare. Ein zusätzlicher Vorteil besteht darin, dass eine ausführliche, sich selbst dokumentierende Freiraum-Modus-Regex in der Zukunft viel wartbarer ist. – ridgerunner

62

Ich muss Alan zustimmen. Wenn die bestehende Regex so kompliziert ist, warum versuchen Sie es in nur einem Regex?

Zerlegen Sie es einfach in ansprechbare einfache Schritte. Das hast du schon gemacht.

Jetzt 4 regex schreiben, um Ihre Teile zu validieren, fügen Sie grundlegende Logik zu den 4 regex hinzu und messen Sie die Länge der Schnur. Erledigt.

Was würden Sie eher debug, dies:

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

oder dies:

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; 
} 

Warum Leute das Gefühl haben, einen regulären Ausdruck schreiben dass niemand verstehen kann, nur damit sie es auf einmal tun können, ist über mich hinaus ...

Ok ok - Wenn Sie wirklich eine einzige Regex wollen, erfahren Sie mehr über lookaheads um Ihre Regeln zu validieren.

Dieses Monster macht, was man in einem Rutsch gefragt:

^          # 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

Ich mag diese Lösung; schön und klar, was vor sich geht, während es einigermaßen prägnant ist. +1 – andrhamm

+0

@andrhamm Gibt es eine Möglichkeit, die ersten beiden Zeilen zu verbinden? Obere oder untere Zeichen nicht oben UND unten? – Byakugan

+0

@Byakugan versuchen $ r1 = '/ [A-Za-z] /'; // Groß- oder Kleinbuchstaben – andrhamm