Regexp Java zur Kennwortüberprüfung

109

Ich erstelle einen regulären Ausdruck für die Kennwortüberprüfung, der in einer Java-Anwendung als Konfigurationsparameter verwendet wird.

Der reguläre Ausdruck ist:

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

Die Passwortrichtlinie lautet:

  • Mindestens 8 Zeichen

  • Enthält mindestens eine Ziffer

  • Enthält mindestens ein unteres Alpha-Zeichen und ein oberes Alpha-Zeichen

  • Enthält mindestens ein Zeichen innerhalb eines Satzes von Sonderzeichen ( @#%$^usw.)

  • Enthält kein Leerzeichen, keine Registerkarte usw.

Ich vermisse nur Punkt 5. Ich kann den regulären Ausdruck nicht auf Speicherplatz, Tabulator, Wagenrücklauf usw. überprüfen lassen.

Könnte mir jemand helfen?

Kerby82
quelle
3
Passwortregeln sind schlecht. Weitere Informationen finden Sie unter Referenz - Passwortüberprüfung .
ctwheels

Antworten:

316

Versuche dies:

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

Erläuterung:

^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # an upper case letter must occur at least once
(?=.*[@#$%^&+=])  # a special character must occur at least once
(?=\S+$)          # no whitespace allowed in the entire string
.{8,}             # anything, at least eight places though
$                 # end-of-string

Es ist einfach, einzelne Regeln hinzuzufügen, zu ändern oder zu entfernen, da jede Regel ein unabhängiges "Modul" ist.

Das (?=.*[xyz])Konstrukt frisst den gesamten String ( .*) und zieht sich zum ersten Vorkommen zurück, wo [xyz]es übereinstimmen kann. Es ist erfolgreich, wenn [xyz]es gefunden wird, andernfalls schlägt es fehl.

Die Alternative wäre die Verwendung eines widerstrebenden Qualifikators : (?=.*?[xyz]). Für eine Passwortprüfung macht dies kaum einen Unterschied, für viel längere Zeichenfolgen könnte es die effizientere Variante sein.

Die effizienteste Variante (aber am schwersten zu lesen und zu warten, daher am fehleranfälligsten) wäre (?=[^xyz]*[xyz])natürlich. Für einen regulären Ausdruck dieser Länge und für diesen Zweck würde ich es nicht empfehlen, dies so zu tun, da es keine wirklichen Vorteile hat.

Tomalak
quelle
15
@ Kerby82: In Java-Strings müssen Backslashes maskiert werden. Versuchen Sie zu verwenden \\s. Dies ist eine Java-Anforderung, keine Regex-Anforderung.
Tomalak
1
@Allov Stellen Sie sich das einfach so vor: Alles, was nicht erzwungen wird, ist optional. Entfernen Sie einfach die Überprüfungen für Dinge, die Sie nicht erzwingen möchten. Sollte einfach sein, die Lösung an Ihre Bedürfnisse anzupassen.
Tomalak
3
Diese Antwort wurde zu den häufig gestellten Fragen zum Stapelüberlauf für reguläre Ausdrücke unter "Allgemeine Validierungsaufgaben" hinzugefügt .
Aliteralmind
1
@ shA.t Es ist das gleiche. Ich habe nur versucht, das (?=...)Muster so zu halten , dass es mit dem Setup des restlichen Ausdrucks
übereinstimmt
2
@ shA.t Ob Sie sagen "enthält nur Leerzeichen" ( (?=\S+$)) oder "enthält keine Leerzeichen" ( (?!.*\s)), ist eine Frage der Präferenz. Verwenden Sie, was Sie besser mögen. :)
Tomalak
55

einfaches Beispiel mit Regex

public class passwordvalidation {
    public static void main(String[] args) {
      String passwd = "aaZZa44@"; 
      String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
      System.out.println(passwd.matches(pattern));
   }
}

Erklärungen:

  • (?=.*[0-9]) Eine Ziffer muss mindestens einmal vorkommen
  • (?=.*[a-z]) Ein Kleinbuchstabe muss mindestens einmal vorkommen
  • (?=.*[A-Z]) Ein Großbuchstabe muss mindestens einmal vorkommen
  • (?=.*[@#$%^&+=]) Ein Sonderzeichen muss mindestens einmal vorkommen
  • (?=\\S+$) In der gesamten Zeichenfolge ist kein Leerzeichen zulässig
  • .{8,} mindestens 8 Zeichen
agiles
quelle
5
{5,10} steht für mindestens 5 Zeichen und maximal 10 Zeichen. Nur für den Fall, dass jemand nach einer konkreten Erklärung sucht.
Abhy
@iabhi, ich habe danach gesucht. Danke dir.
Akshatha Srinivas
Ich versuche aus Sicherheitsgründen, Regex für ein Kennwort zu implementieren, das in einem char-Array anstelle eines Strings gespeichert ist. Aber wie wendet man Regex auf ein Char-Array an?
AgentM
13

Alle zuvor gegebenen Antworten verwenden dieselbe (richtige) Technik, um für jede Anforderung einen eigenen Lookahead zu verwenden. Sie enthalten jedoch einige Ineffizienzen und einen potenziell massiven Fehler, abhängig vom Back-End, das das Kennwort tatsächlich verwendet.

Ich beginne mit dem regulären Ausdruck der akzeptierten Antwort:

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

Erstens, da Java unterstützt \Aund \zich diese lieber verwende, um sicherzustellen, dass die gesamte Zeichenfolge unabhängig von validiert wird Pattern.MULTILINE. Dies wirkt sich nicht auf die Leistung aus, vermeidet jedoch Fehler beim Recycling von Regexen.

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

Das Überprüfen, ob das Kennwort kein Leerzeichen enthält, und das Überprüfen seiner Mindestlänge können in einem einzigen Durchgang durchgeführt werden, indem alle auf einmal verwendet werden, indem ein variabler Quantifizierer {8,}in die Kurzform eingefügt wird \S, die die zulässigen Zeichen begrenzt:

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

Wenn das angegebene Kennwort ein Leerzeichen enthält, werden alle Überprüfungen durchgeführt, sodass die endgültige Überprüfung des Leerzeichens fehlschlägt. Dies kann vermieden werden, indem alle Punkte durch Folgendes ersetzt werden \S:

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

Der Punkt sollte nur verwendet werden, wenn Sie wirklich ein Zeichen zulassen möchten. Verwenden Sie andernfalls eine (negierte) Zeichenklasse, um Ihren regulären Ausdruck nur auf die Zeichen zu beschränken, die wirklich zulässig sind. Obwohl es in diesem Fall kaum einen Unterschied macht, ist es eine sehr gute Angewohnheit , den Punkt nicht zu verwenden, wenn etwas anderes angemessener ist. Ich sehe viel zu viele Fälle von katastrophalem Backtracking, weil der Entwickler zu faul war, um etwas passenderes als den Punkt zu verwenden.

Da es eine gute Chance gibt, dass die ersten Tests in der ersten Hälfte des Passworts ein geeignetes Zeichen finden, kann ein fauler Quantifizierer effizienter sein:

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

Aber jetzt zum wirklich wichtigen Thema: Keine der Antworten erwähnt die Tatsache, dass die ursprüngliche Frage von jemandem geschrieben zu sein scheint, der in ASCII denkt. Aber in Java sind Strings Unicode. Sind Nicht-ASCII-Zeichen in Passwörtern zulässig? Wenn dies der Fall ist, sind nur ASCII-Leerzeichen nicht zulässig, oder sollten alle Unicode-Leerzeichen ausgeschlossen werden.

Standardmäßig werden \snur ASCII-Leerzeichen abgeglichen, sodass die Umkehrung \Smit allen Unicode-Zeichen (Leerzeichen oder nicht) und allen Nicht-Leerzeichen-ASCII-Zeichen übereinstimmt. Wenn Unicode-Zeichen zulässig sind, Unicode-Leerzeichen jedoch nicht, kann das UNICODE_CHARACTER_CLASSFlag angegeben werden, \Sum Unicode-Leerzeichen auszuschließen. Wenn Unicode-Zeichen nicht zulässig sind, [\x21-\x7E]können sie stattdessen verwendet werden \S, um alle ASCII-Zeichen abzugleichen, die kein Leerzeichen oder Steuerzeichen sind.

Das bringt uns zum nächsten möglichen Problem: Wollen wir Steuerzeichen zulassen? Der erste Schritt beim Schreiben eines richtigen regulären Ausdrucks besteht darin, genau anzugeben, was Sie abgleichen möchten und was nicht. Die einzige technisch korrekte Antwort von 100% ist, dass die Kennwortspezifikation in der Frage nicht eindeutig ist, da nicht angegeben wird, ob bestimmte Zeichenbereiche wie Steuerzeichen oder Nicht-ASCII-Zeichen zulässig sind oder nicht.

Jan Goyvaerts
quelle
9

Sie sollten nicht zu komplexe Regex verwenden (wenn Sie sie vermeiden können), da dies der Fall ist

  • schwer zu lesen (zumindest für alle außer dir)
  • schwer zu verlängern
  • schwer zu debuggen

Obwohl die Verwendung vieler kleiner regulärer Ausdrücke einen geringen Leistungsaufwand mit sich bringt, können die obigen Punkte ihn leicht übergewichten.

Ich würde so implementieren:

bool matchesPolicy(pwd) {
    if (pwd.length < 8) return false;
    if (not pwd =~ /[0-9]/) return false;
    if (not pwd =~ /[a-z]/) return false;
    if (not pwd =~ /[A-Z]/) return false;
    if (not pwd =~ /[%@$^]/) return false;
    if (pwd =~ /\s/) return false;
    return true;
}
Martin Rauscher
quelle
Aus Sicherheitsgründen ist es weitaus besser, längere Passwörter zu erzwingen, bekannte Passwörter (wie 12345 und pass = user) zu verhindern, als Passwörter sehr kompliziert und schwer zu merken.
Martin Rauscher
Ich mag Ihren Ansatz oben. Danke für das!
Thomas Lang
1

Passwortanforderung:

  • Das Kennwort sollte mindestens acht (8) Zeichen lang sein, sofern das System dies unterstützen kann.
  • Kennwörter müssen Zeichen aus mindestens zwei (2) dieser Gruppierungen enthalten: Alpha-, numerische und Sonderzeichen.

    ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$

Ich habe es getestet und es funktioniert

Andrew
quelle
1

Für alle, die an Mindestanforderungen für jeden Charaktertyp interessiert sind, würde ich empfehlen, die folgende Erweiterung über Tomalaks akzeptierte Antwort vorzunehmen:

^(?=(.*[0-9]){%d,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$

Beachten Sie, dass dies eine Formatierungszeichenfolge und nicht das endgültige Regex-Muster ist. Ersetzen Sie% d einfach durch die minimal erforderlichen Vorkommen für: Ziffern, Kleinbuchstaben, Großbuchstaben, Nicht-Ziffern / Zeichen und das gesamte Kennwort (jeweils). Maximale Vorkommen sind unwahrscheinlich (es sei denn, Sie möchten ein Maximum von 0, wodurch solche Zeichen effektiv abgelehnt werden), aber diese können auch leicht hinzugefügt werden. Beachten Sie die zusätzliche Gruppierung um jeden Typ, sodass die Min / Max-Einschränkungen nicht aufeinanderfolgende Übereinstimmungen ermöglichen. Dies wirkte Wunder für ein System, in dem wir zentral konfigurieren konnten, wie viele Zeichen jeder Art von Zeichen wir benötigten, und dann die Website sowie zwei verschiedene mobile Plattformen diese Informationen abrufen konnten, um das Regex-Muster basierend auf der obigen Formatierungszeichenfolge zu erstellen.

Demetrios Christopher
quelle
1

Dieser prüft auf jedes Sonderzeichen:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\S+$).*[A-Za-z0-9].{8,}$
Ansu
quelle
1

Java-Methode für Sie bereit, mit Parametern

Kopieren und fügen Sie einfach die gewünschten Parameter ein und stellen Sie sie ein.

Wenn Sie kein Modul möchten, kommentieren Sie es einfach oder fügen Sie ein "Wenn" hinzu, wie von mir für ein spezielles Zeichen

//______________________________________________________________________________
/**
 * Validation Password     */
//______________________________________________________________________________
private static boolean validation_Password(final String PASSWORD_Arg)    {
    boolean result = false;
    try {
        if (PASSWORD_Arg!=null) {
            //_________________________
            //Parameteres
            final String MIN_LENGHT="8";
            final String MAX_LENGHT="20";
            final boolean SPECIAL_CHAR_NEEDED=true;

            //_________________________
            //Modules
            final String ONE_DIGIT = "(?=.*[0-9])";  //(?=.*[0-9]) a digit must occur at least once
            final String LOWER_CASE = "(?=.*[a-z])";  //(?=.*[a-z]) a lower case letter must occur at least once
            final String UPPER_CASE = "(?=.*[A-Z])";  //(?=.*[A-Z]) an upper case letter must occur at least once
            final String NO_SPACE = "(?=\\S+$)";  //(?=\\S+$) no whitespace allowed in the entire string
            //final String MIN_CHAR = ".{" + MIN_LENGHT + ",}";  //.{8,} at least 8 characters
            final String MIN_MAX_CHAR = ".{" + MIN_LENGHT + "," + MAX_LENGHT + "}";  //.{5,10} represents minimum of 5 characters and maximum of 10 characters

            final String SPECIAL_CHAR;
            if (SPECIAL_CHAR_NEEDED==true) SPECIAL_CHAR= "(?=.*[@#$%^&+=])"; //(?=.*[@#$%^&+=]) a special character must occur at least once
            else SPECIAL_CHAR="";
            //_________________________
            //Pattern
            //String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
            final String PATTERN = ONE_DIGIT + LOWER_CASE + UPPER_CASE + SPECIAL_CHAR + NO_SPACE + MIN_MAX_CHAR;
            //_________________________
            result = PASSWORD_Arg.matches(PATTERN);
            //_________________________
        }    

    } catch (Exception ex) {
        result=false;
    }

    return result;
}        
Fausto70
quelle
1

Verwenden Sie die Passay- Bibliothek, die eine leistungsstarke API ist.

Balasubramanian Rengasamy
quelle
0

Ich denke, das kann es auch (als einfacherer Modus):

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

[Regex Demo]

shA.t.
quelle
0

Einfaches

("^ (? =. * [0-9]) (? =. * [Az]) (? =. * [AZ]) (? =. * [\\ W _]) [\\ S] {8 , 10} $ ")

  1. (? = irgendetwas) -> bedeutet, dass in allen Eingabezeichenfolgen ein positiver Blick nach vorne gerichtet ist und dass diese Bedingung geschrieben ist .sample (? =. * [0-9]) -> bedeutet, dass in die gesamte Zeichenfolge eine einstellige Zahl geschrieben ist. Wenn nicht geschrieben, geben Sie false zurück .

  2. (?! Alles) -> (umgekehrt) bedeutet negative Blicke nach vorne , wenn Bedingung geschrieben Rückkehr falsch .

    nahe Bedeutung ^ (Bedingung) (Bedingung) (Bedingung) (Bedingung) [\ S] {8,10} $

Ibrahem Shabban
quelle
Während nur Code-Antworten eine Lösung für das Problem darstellen können, würde eine Erklärung die Qualität der Antwort erheblich verbessern.
Nigel Ren
0
String s=pwd;
int n=0;
for(int i=0;i<s.length();i++)
{
    if((Character.isDigit(s.charAt(i))))
    {
        n=5;
        break;
    }
    else
    {

    }
}
for(int i=0;i<s.length();i++)
{
    if((Character.isLetter(s.charAt(i))))
    {
        n+=5;
        break;
    }
    else
    {

    }

}

if(n==10)
{
    out.print("Password format correct <b>Accepted</b><br>");

}
else
{
    out.print("Password must be alphanumeric <b>Declined</b><br>");
}

Erläuterung:

  1. Legen Sie zuerst das Kennwort als Zeichenfolge fest und erstellen Sie eine Ganzzahl.
  2. Überprüfen Sie dann die einzelnen Zeichen für die for-Schleife.
  3. Wenn es eine Zahl in der Zeichenfolge findet, addiert das n 5. Dann springe zur nächsten for-Schleife. Character.isDigit (s.charAt (i))
  4. Diese Schleife überprüft alle in der Zeichenfolge platzierten Alphabete. Wenn es gefunden wird, fügen Sie eine weitere 5 in n hinzu. Character.isLetter (s.charAt (i))
  5. Überprüfen Sie nun die Ganzzahl n anhand der if-Bedingung. Wenn n = 10 wahr ist, ist die Zeichenfolge alphanumerisch, andernfalls nicht.
Naresh Babu
quelle
0

Auch Sie können dies tun.

 public boolean isPasswordValid(String password) {


    String regExpn =
            "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";

    CharSequence inputStr = password;

    Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(inputStr);

    if(matcher.matches())
        return true;
    else
        return false;
}
RANAJEET BARIK
quelle
0

Beispielcodeblock für sicheres Passwort:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. mindestens 6 Ziffern
  2. bis zu 18 Stellen
  3. eine Nummer
  4. ein Kleinbuchstabe
  5. ein Großbuchstabe
  6. kann alle Sonderzeichen enthalten
Sedrettin Çalışkan
quelle
0

RegEx ist -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. mindestens 8 Stellen {8,}
  2. mindestens eine Zahl (? =. * \ d)
  3. mindestens ein Kleinbuchstabe (? =. * [az])
  4. mindestens ein Großbuchstabe (? =. * [AZ])
  5. mindestens ein Sonderzeichen (? =. * [@ # $% ^ & + =])
  6. Kein Leerzeichen [^ \ s]
Ankit Kumar Rajpoot
quelle