Regex zur Überprüfung der Kennwortstärke


142

Meine Kriterien für die Kennwortstärke lauten wie folgt:

  • 8 Zeichen Länge
  • 2 Buchstaben in Großbuchstaben
  • 1 Sonderzeichen (!@#$&*)
  • 2 Ziffern (0-9)
  • 3 Buchstaben in Kleinbuchstaben

Kann mir bitte jemand Regex dafür geben? Alle Bedingungen müssen per Passwort erfüllt sein.


2
Sind Sie wirklich bereit, Ihre Kennwortsicherheitsmaßnahmen dem Internet insgesamt anzuvertrauen?
Borealid

12
@Borealid: Das Veröffentlichen Ihrer Kennwortrichtlinien sollte Ihre Sicherheit normalerweise nicht wesentlich beeinträchtigen. Wenn dies der Fall ist, sind Ihre Richtlinien schlecht ("Nur passwordund hello123sind gültige Passwörter!").
Joachim Sauer

3
@ Joachim Sauer: Das habe ich nicht gemeint. Was ich damit meinte war, dass das Poster wahrscheinlich nur dem regulären Ausdruck vertrauen wird, den er erhält. Keine so gute Idee.
Borealid

3
Eigentlich wird dieser Regex im Service-Code sein, ich werde auf verschiedene Fälle testen, denen ich nicht blind vertraue :)
Ajay Kelkar

9
Komplexe Passwortregeln führen normalerweise nicht zu sichereren Passwörtern. Wichtig ist nur eine Mindestlänge. Menschen können sich nicht an unzählige sichere Passwörter erinnern, und solche Regeln können gute Passwortschemata beeinträchtigen. Menschen können sehr erfinderisch werden, um solche Regeln zu umgehen, z. B. indem sie schwache Passwörter wie "Password-2014" verwenden. Oft haben Sie schwächere Passwörter als stärkere.
Martinstoeckli

Antworten:


427

Sie können diese Überprüfungen mit positiven Vorausschau-Aussagen durchführen:

^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$

Rubular Link

Erläuterung:

^                         Start anchor
(?=.*[A-Z].*[A-Z])        Ensure string has two uppercase letters.
(?=.*[!@#$&*])            Ensure string has one special case letter.
(?=.*[0-9].*[0-9])        Ensure string has two digits.
(?=.*[a-z].*[a-z].*[a-z]) Ensure string has three lowercase letters.
.{8}                      Ensure string is of length 8.
$                         End anchor.

92
Für alle, die mindestens eine Länge wünschen n, ersetzen Sie .{8}durch.{n,}
NullUserException

14
+1 für eine vollständige Erklärung. Meine Passwortregeln sind unterschiedlich, aber basierend auf Ihrer Antwort kann ich den regulären Ausdruck anpassen.
Morvael

14
Vielen Dank, dass Sie beschrieben haben, was in der Regex passiert. Dies ist ein großartiges Lernbeispiel für diejenigen von uns, die sich mit der Syntax noch nie wirklich verstanden haben.

4
Ich schätze auch die Erklärung des regulären Ausdrucks. Zu oft verwende ich komplexe Regex, die ich gefunden habe, ohne wirklich zu verstehen, was los ist.
Nicholas Smith

4
Tolles Muster, ich frage mich, warum man keine Quantifizierer verwendet. Mindestens 1 Sonderzeichen, 1 Zahl, 1 Sonderzeichen, 8 Zeichen: ^ (? =. * ([AZ]) {1,}) (? =. * [! @ # $ & *] {1,}) ( ? =. * [0-9] {1,}) (? =. * [Az] {1,}). {8,100} $
RockOnGom

11

Sie können positive Look-Aheads mit der Länge Null verwenden, um jede Ihrer Einschränkungen separat anzugeben:

(?=.{8,})(?=.*\p{Lu}.*\p{Lu})(?=.*[!@#$&*])(?=.*[0-9])(?=.*\p{Ll}.*\p{Ll})

Wenn Ihr Regex - Engine , die nicht unterstützt \pNotation und reine ASCII genug ist, dann können Sie ersetzen \p{Lu}mit [A-Z]und \p{Ll}mit [a-z].


8

Die oben angegebenen Antworten sind perfekt, aber ich empfehle , mehrere kleinere Regex anstelle eines großen zu verwenden.
Das Aufteilen des langen regulären Ausdrucks hat einige Vorteile:

  • Leichtigkeit zu schreiben und zu lesen
  • Leichtigkeit zu debuggen
  • Leichtigkeit, einen Teil des regulären Ausdrucks hinzuzufügen / zu entfernen

Im Allgemeinen hält dieser Ansatz den Code leicht wartbar .

Trotzdem teile ich einen Code, den ich in Swift schreibe, als Beispiel:

struct RegExp {

    /**
     Check password complexity

     - parameter password:         password to test
     - parameter length:           password min length
     - parameter patternsToEscape: patterns that password must not contains
     - parameter caseSensitivty:   specify if password must conforms case sensitivity or not
     - parameter numericDigits:    specify if password must conforms contains numeric digits or not

     - returns: boolean that describes if password is valid or not
     */
    static func checkPasswordComplexity(password password: String, length: Int, patternsToEscape: [String], caseSensitivty: Bool, numericDigits: Bool) -> Bool {
        if (password.length < length) {
            return false
        }
        if caseSensitivty {
            let hasUpperCase = RegExp.matchesForRegexInText("[A-Z]", text: password).count > 0
            if !hasUpperCase {
                return false
            }
            let hasLowerCase = RegExp.matchesForRegexInText("[a-z]", text: password).count > 0
            if !hasLowerCase {
                return false
            }
        }
        if numericDigits {
            let hasNumbers = RegExp.matchesForRegexInText("\\d", text: password).count > 0
            if !hasNumbers {
                return false
            }
        }
        if patternsToEscape.count > 0 {
            let passwordLowerCase = password.lowercaseString
            for pattern in patternsToEscape {
                let hasMatchesWithPattern = RegExp.matchesForRegexInText(pattern, text: passwordLowerCase).count > 0
                if hasMatchesWithPattern {
                    return false
                }
            }
        }
        return true
    }

    static func matchesForRegexInText(regex: String, text: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = text as NSString
            let results = regex.matchesInString(text,
                options: [], range: NSMakeRange(0, nsString.length))
            return results.map { nsString.substringWithRange($0.range)}
        } catch let error as NSError {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }
}

Wenn Sie komplexe Regex wie oben verwenden, ist es sehr einfach, sich für katastrophales Backtracking zu öffnen ( regulär-expressions.info / catastrophic.html ). Dies kann unbemerkt bleiben, bis Ihr Server eines Tages mit 100% CPU hängt, weil ein Benutzer ein "seltsames" Passwort verwendet hat. Beispiel: ^ ([a-z0-9] +) {8,} $ (können Sie den Fehler sehen?)
aKzenT

5

Ich würde vorschlagen, hinzuzufügen

(?!.*pass|.*word|.*1234|.*qwer|.*asdf) exclude common passwords

1

Die Lösung von codaddict funktioniert einwandfrei, aber diese ist etwas effizienter: (Python-Syntax)

password = re.compile(r"""(?#!py password Rev:20160831_2100)
    # Validate password: 2 upper, 1 special, 2 digit, 1 lower, 8 chars.
    ^                        # Anchor to start of string.
    (?=(?:[^A-Z]*[A-Z]){2})  # At least two uppercase.
    (?=[^!@#$&*]*[!@#$&*])   # At least one "special".
    (?=(?:[^0-9]*[0-9]){2})  # At least two digit.
    .{8,}                    # Password length is 8 or more.
    $                        # Anchor to end of string.
    """, re.VERBOSE)

Die negierten Zeichenklassen verbrauchen in einem einzigen Schritt alles bis zum gewünschten Zeichen und erfordern kein Backtracking. (Die Dot-Star-Lösung funktioniert einwandfrei, erfordert jedoch ein gewisses Backtracking.) Bei kurzen Zielzeichenfolgen wie Kennwörtern ist diese Effizienzverbesserung natürlich vernachlässigbar.


Könnten Sie bitte überprüfen, ob es korrekt ist? Ich bin im Zweifel, weil ich in der ersten Zeile zwischen Triple Doublequote und Fragezeichen eine runde Klammer öffne. Ich kann sehen, dass Python-Kommentar (Hash) später ist. Ich kann keinen Korrespondenten sehen, der die runde Klammer in der Nähe des Endankers schließt (Dollarzeichen). Sollte erwähnen, dass ich kein Regex-Profy bin.
Lospejos

@lospejos - Das # ist nicht der Beginn eines regulären einzeiligen Kommentars. Dieser Hash ist Teil einer Kommentargruppe, die mit a beginnt und mit a (?#endet ). Es gibt keine unausgeglichenen Eltern in dieser Regex.
Ridgerunner

1
import re

RegexLength=re.compile(r'^\S{8,}$')
RegexDigit=re.compile(r'\d')
RegexLower=re.compile(r'[a-z]')
RegexUpper=re.compile(r'[A-Z]')


def IsStrongPW(password):
    if RegexLength.search(password) == None or RegexDigit.search(password) == None or RegexUpper.search(password) == None or RegexLower.search(password) == None:
        return False
    else:
        return True

while True:
    userpw=input("please input your passord to check: \n")
    if userpw == "exit":
        break
    else:
        print(IsStrongPW(userpw))

1

Die Lösung von @ codaddict wird funktionieren.

Sie sollten auch in Betracht ziehen, einige Ihrer Regeln zu ändern:

  1. Fügen Sie weitere Sonderzeichen hinzu, z. B.%, ^, (,), -, _, + und Punkt. Ich füge alle Sonderzeichen hinzu, die Sie über den Nummernzeichen in US-Tastaturen verpasst haben. Entfliehen Sie denjenigen, die Regex verwendet.
  2. Machen Sie das Passwort 8 oder mehr Zeichen. Nicht nur eine statische Zahl 8.

Mit den oben genannten Verbesserungen und für mehr Flexibilität und Lesbarkeit würde ich den regulären Ausdruck auf ändern.

^(?=.*[a-z]){3,}(?=.*[A-Z]){2,}(?=.*[0-9]){2,}(?=.*[!@#$%^&*()--__+.]){1,}.{8,}$

Grundlegende Erklärung

(?=.*RULE){MIN_OCCURANCES,}     Each rule block is shown by (){}. The rule and number of occurrences can then be easily specified and tested separately, before getting combined

Ausführliche Erklärung

^                             start anchor
(?=.*[a-z]){3,}               lowercase letters. {3,} indicates that you want 3 of this group
(?=.*[A-Z]){2,}               uppercase letters. {2,} indicates that you want 2 of this group
(?=.*[0-9]){2,}               numbers. {2,} indicates that you want 2 of this group
(?=.*[!@#$%^&*()--__+.]){1,}   all the special characters in the [] fields. The ones used by regex are escaped by using the \ or the character itself. {1,} is redundant, but good practice, in case you change that to more than 1 in the future. Also keeps all the groups consistent
{8,}                          indicates that you want 8 or more
$                             end anchor

Und zu Testzwecken gibt es hier einen Robulink mit dem obigen regulären Ausdruck


Danke @AFract. Ich benutze es in meinem Code. Ich mag Lesbarkeit und Wiederholbarkeit, wenn Sie zurückgehen und es in Zukunft ändern müssen, dh im Falle einer Änderung der Passwortrichtlinie :)
lsu_guy

0

Für PHP funktioniert das gut!

 if(preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 
 'CaSu4Li8')){
    return true;
 }else{
    return fasle;
 }

In diesem Fall ist das Ergebnis wahr

Danke für @ridgerunner


warum nicht return preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 'CaSu4Li8')?
Aloisdg wechselt zu codidact.com

0

Eine andere Lösung:

import re

passwordRegex = re.compile(r'''(
    ^(?=.*[A-Z].*[A-Z])                # at least two capital letters
    (?=.*[!@#$&*])                     # at least one of these special c-er
    (?=.*[0-9].*[0-9])                 # at least two numeric digits
    (?=.*[a-z].*[a-z].*[a-z])          # at least three lower case letters
    .{8,}                              # at least 8 total digits
    $
    )''', re.VERBOSE)

def userInputPasswordCheck():
    print('Enter a potential password:')
    while True:
        m = input()
        mo = passwordRegex.search(m) 
        if (not mo):
           print('''
Your password should have at least one special charachter,
two digits, two uppercase and three lowercase charachter. Length: 8+ ch-ers.

Enter another password:''')          
        else:
           print('Password is strong')
           return
userInputPasswordCheck()

0

Das Passwort muss mindestens 3 der folgenden 4 Komplexitätsregeln erfüllen:

[mindestens 1 Großbuchstabe (AZ) mindestens 1 Kleinbuchstabe (az) mindestens 1 Ziffer (0-9) mindestens 1 Sonderzeichen - vergessen Sie nicht, Leerzeichen auch als Sonderzeichen zu behandeln]

mindestens 10 Zeichen

höchstens 128 Zeichen

nicht mehr als 2 identische Zeichen hintereinander (z. B. 111 nicht erlaubt)

'^ (?!. (.) \ 1 {2}) ((? =. [Az]) (? =. [AZ]) (? =. [0-9]) | (? =. [Az] ) (? =. [AZ]) (? =. [^ A-zA-Z0-9]) | (? =. [AZ]) (? =. [0-9]) (? =. [^ A. -zA-Z0-9]) | (? =. [az]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])). {10,127} $ '

(?!. * (.) \ 1 {2})

(? =. [az]) (? =. [AZ]) (? =. * [0-9])

(? =. [az]) (? =. [AZ]) (? =. * [^ a-zA-Z0-9])

(? =. [AZ]) (? =. [0-9]) (? =. * [^ A-zA-Z0-9])

(? =. [az]) (? =. [0-9]) (? =. * [^ a-zA-Z0-9])

{10.127}


0

Alle oben genannten Regex haben bei mir leider nicht funktioniert. Die Grundregeln eines starken Passworts sind

  • Sollte mindestens einen Großbuchstaben enthalten
  • Sollte mindestens einen kleinen Buchstaben enthalten
  • Sollte mindestens eine Nummer enthalten
  • Sollte mindestens ein Sonderzeichen enthalten
  • Und minimale Länge

Also, Best Regex wäre

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

Der obige reguläre Ausdruck hat eine Mindestlänge von 8. Sie können ihn von {8,} in { any_number ,} ändern .

Änderung der Regeln?

Nehmen wir an, Sie möchten mindestens x Kleinbuchstaben, y Großbuchstaben, Z- Zeichen, Mindestgesamtlänge w . Dann versuchen Sie es unter Regex

^(?=.*[a-z]{x,})(?=.*[A-Z]{y,})(?=.*[0-9]{z,})(?=.*[!@#\$%\^&\*]).{w,}$

Hinweis: Ändern Sie x , y , z , w in Regex

Bearbeiten: Regex-Antwort aktualisiert

Edit2: Änderung hinzugefügt


Ihre regex ist passend 12345678sind Sie sicher , es ist ein starkes Passwort? Bitte versuchen Sie es vor dem Posten mit Ihrer Regex.
Toto

Das ist besser, beantwortet aber nicht die Frage, sie wollen 1) 8 Zeichen Länge. 2) 2 Buchstaben in Großbuchstaben. 3) 1 Sonderzeichen (! @ # $ & *). 4) 2 Ziffern (0-9). 5) 3 Buchstaben in Kleinbuchstaben.
Toto

@Toto Kannst du bitte jetzt deine Gedanken teilen?
Juned Khatri

Ihre Regex berücksichtigt nicht, dass die 2 obligatorischen Großbuchstaben durch andere Zeichen getrennt werden können, dieselbe Bemerkung für Kleinbuchstaben und Ziffern. Die gültige Antwort ist die, die akzeptiert wurde.
Toto
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.