2010-08-12 15 views
30

Ich habe die folgenden Kriterien für die Erstellung einer regulären Ausdruck für ein Kennwort zu erzwingen, die den folgenden Regeln entspricht:Regulärer Ausdruck komplexe Passwörter, passende 3 von 4 Regeln

  1. Das Passwort 8 Zeichen lang sein müssen (das kann ich machen :-)).

Das Passwort muss dann Zeichen aus mindestens drei der folgenden vier Regeln enthalten:

  1. Ober Fall
  2. Kleinbuchstaben
  3. Zahlen
  4. Nicht-alphanumerische

Ich kann den Ausdruck alle diese Regeln mit dem folgenden Ausdruck übereinstimmen:

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

Aber ich habe Schwierigkeiten damit, wie diese Weise in einer solchen zu tun, dass es nur jede 3 der 4 Regeln lösen muss.

Kann mir jemand dabei helfen?

+7

ich muss sagen, dass dies einer der Fälle ist, wenn ich Ihren Code denken wahrscheinlich viel sein würde besser lesbar, wenn Sie stattdessen 4 verschiedene Regexs hätten. Und dann vielleicht eine Zählung und für jede der Regex, die Sie übereinstimmen, erhöhen Sie die Anzahl und dann am Ende Sie nur überprüfen, ob die Zählung 3 oder höher ist. –

+0

Welche Programmiersprache benutzen Sie? – kennytm

Antwort

73

Verwenden Sie keine Regex, um es dann zu überprüfen.

if (password.length < 8) 
    alert("bad password"); 
var hasUpperCase = /[A-Z]/.test(password); 
var hasLowerCase = /[a-z]/.test(password); 
var hasNumbers = /\d/.test(password); 
var hasNonalphas = /\W/.test(password); 
if (hasUpperCase + hasLowerCase + hasNumbers + hasNonalphas < 3) 
    alert("bad password"); 

Wenn Sie eine einzelne Regex verwenden müssen:

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

Diese Regex nicht optimiert ist für die Effizienz. Es wird von A·B·C + A·B·D + A·C·D + B·C·D mit etwas Faktorisierung konstruiert. Zusammensetzung:

^ 
(?: 
    (?=.*[a-z])  # 1. there is a lower-case letter ahead, 
    (?:    # and 
     (?=.*[A-Z]) #  1.a.i) there is also an upper-case letter, and 
     (?=.*[\d\W]) #  1.a.ii) a number (\d) or symbol (\W), 
    |     # or 
     (?=.*\W)  #  1.b.i) there is a symbol, and 
     (?=.*\d)  #  1.b.ii) a number ahead 
    ) 
|      # OR 
    (?=.*\W)   # 2.a) there is a symbol, and 
    (?=.*[A-Z])  # 2.b) an upper-case letter, and 
    (?=.*\d)   # 2.c) a number ahead. 
) 
.{8,}     # the password must be at least 8 characters long. 
$ 
5

Sie könnte schreibt eine wirklich anspruchsvolle regex, das zu tun. Stattdessen würde ich vorschlagen, vier verschiedene Regexes zu schreiben, einen für jede Regel, und sie einzeln zu testen, wobei gezählt wird, wie viele von ihnen übereinstimmen. Wenn drei von vier taten, das Passwort akzeptieren.

1

Ich schlage vor, die Überprüfungen separat durchzuführen und dann zu addieren, wie viele übereinstimmen.

(ich würde auch nicht einen regulären Ausdruck in einer von ihnen verwenden, aber das ist nur meine persönliche POV - nämlich, dass sie die Lesbarkeit behindern und werden in der Regel write-once-Code)

3

Sie die folgende Regex verwenden können:

(^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).*$)?(^(?=.*\d)(?=.*[a-z])(?=.*[@#$%^&+=]).*$)?(^(?=.*\d)(?=.*[A-Z])(?=.*[@#$%^&+=]).*$)?(^(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*$)? 

Mit einem Passwort Mindestlänge von 8 und max Länge 32 können Sie die folgende Regex verwenden:

(^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,32}$)?(^(?=.*\d)(?=.*[a-z])(?=.*[@#$%^&+=]).{8,32}$)?(^(?=.*\d)(?=.*[A-Z])(?=.*[@#$%^&+=]).{8,32}$)?(^(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).{8,32}$)? 
+0

Von vier müssen Sie 3 zu einem Zeitpunkt nehmen und wenn einer davon übereinstimmt, wird das Passwortmuster validiert. – ajithparamban

+3

Warum eine maximale Passwortlänge einstellen? – evolutionxbox