web-dev-qa-db-de.com

Regex Java zur Kennwortüberprüfung

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

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 Zeichen und ein oberes Zeichen

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

  • Enthält keine Leerzeichen, Tabulatoren usw.

Ich vermisse nur Punkt 5. Ich kann den Regex-Ausdruck nicht auf Platz, Registerkarte, Wagenrücklauf usw. überprüfen lassen.

Könnte mir jemand helfen?

88
Kerby82

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 leicht, einzelne Regeln hinzuzufügen, zu ändern oder zu entfernen, da jede Regel ein unabhängiges "Modul" ist.

Das (?=.*[xyz])-Konstrukt frisst die gesamte Zeichenfolge (.*) und führt zum ersten Vorkommen zurück, bei dem [xyz] übereinstimmen kann. Wenn [xyz] gefunden wird, schlägt dies fehl, andernfalls schlägt es fehl. 

Die Alternative wäre die Verwendung eines widerstrebenden Qualifizierers: (?=.*?[xyz]). Bei einer Passwortüberprüfung macht das kaum einen Unterschied, bei längeren Zeichenketten kann es die effizientere Variante sein.

Die effizienteste Variante (aber am schwierigsten zu lesen und zu warten, daher die fehleranfälligste) wäre natürlich (?=[^xyz]*[xyz]). Für einen Regex dieser Länge und zu diesem Zweck würde ich es nicht empfehlen, es so zu machen, da es keinen wirklichen Nutzen hat.

258
Tomalak

einfaches Beispiel mit Regex

public class passwordvalidation {
    public static void main(String[] args) {
      String passwd = "[email protected]"; 
      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
46
agiles

Alle zuvor gegebenen Antworten verwenden dieselbe (richtige) Technik, um für jede Anforderung einen separaten Lookahead zu verwenden. Sie enthalten jedoch einige Ineffizienzen und einen potenziell massiven Fehler, je nachdem, welches Back-End das Passwort tatsächlich verwendet.

Ich fange mit der Regex von der akzeptierten Antwort an:

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

Da Java \A und \z unterstützt, ziehe ich es vor, diese zu verwenden, um sicherzustellen, dass die gesamte Zeichenfolge unabhängig von Pattern.MULTILINE überprüft wird. Dies wirkt sich nicht auf die Leistung aus, vermeidet jedoch Fehler beim Recycling von Regex.

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

Die Überprüfung, dass das Kennwort kein Leerzeichen enthält, und die Überprüfung der Mindestlänge kann in einem einzigen Durchgang durchgeführt werden. Verwenden Sie all all auf einmal, indem Sie den Variablenquantifizierer {8,} in das Kürzel \S setzen, das die zulässigen Zeichen begrenzt:

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

Wenn das bereitgestellte Kennwort ein Leerzeichen enthält, werden alle Überprüfungen durchgeführt, nur damit die letzte Überprüfung des Leerzeichens fehlschlägt. Dies kann vermieden werden, indem alle Punkte durch \S ersetzt werden:

\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 Ihre Regex auf nur die Zeichen zu beschränken, die wirklich zulässig sind. In diesem Fall macht es wenig aus, den Punkt nicht zu verwenden, wenn etwas anderes angemessener ist ist eine sehr gute Angewohnheit. Ich sehe viel zu viele Fälle von katastrophales Backtracking , weil der Entwickler zu faul war, etwas passenderes als den Punkt zu verwenden.

Da es gute Chancen gibt, dass die ersten Tests in der ersten Hälfte des Passworts ein passendes Zeichen finden, kann ein Lazer-Quantifier effizienter sein:

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

Nun aber zu dem wirklich wichtigen Thema: In keiner der Antworten wird die Tatsache erwähnt, dass die ursprüngliche Frage von jemandem geschrieben wurde, der in ASCII denkt. In Java sind Strings jedoch Unicode. Sind nicht-ASCII-Zeichen in Kennwörtern zulässig? Wenn dies der Fall ist, sind nur Leerzeichen ASCII unzulässig oder sollten alle Unicode-Leerzeichen ausgeschlossen werden.

Standardmäßig entspricht \s nur ASCII Whitespace, daher entspricht der inverse \S allen Unicode-Zeichen (Whitespace oder nicht) und allen Nicht-Whitespace-Zeichen ASCII. Wenn Unicode-Zeichen zulässig sind, Unicode-Leerzeichen jedoch nicht, kann das Flag UNICODE_CHARACTER_CLASS angegeben werden, um \S Unicode-Whitespace auszuschließen. Wenn Unicode-Zeichen nicht zulässig sind, kann [\x21-\x7E] anstelle von \S verwendet werden, um alle ASCII - Zeichen abzugleichen, die kein Leerzeichen oder Steuerzeichen sind.

Das bringt uns zur nächsten möglichen Frage: Wollen wir Steuerzeichen zulassen? Der erste Schritt beim Schreiben einer richtigen Regex ist, genau anzugeben, was Sie anpassen möchten und was nicht. Die einzige zu 100% technisch korrekte Antwort ist, dass die Kennwortangabe in der Frage mehrdeutig ist, da nicht angegeben wird, ob bestimmte Zeichenbereiche wie Steuerzeichen oder Nicht-ASCII-Zeichen zulässig sind oder nicht.

10
Jan Goyvaerts

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

  • schwer zu lesen (zumindest für jeden außer Ihnen)
  • schwer zu erweitern
  • schwer zu debuggen

Obwohl bei der Verwendung vieler kleiner regulärer Ausdrücke ein geringer Performance-Aufwand anfallen kann, sind die Punkte übergewichtig.

Ich würde so umsetzen:

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;
}
8
Martin Rauscher

Passwortanforderung:

  • Das Passwort sollte mindestens acht (8) Zeichen lang sein, sofern das System es 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)(?=.*[[email protected]#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[[email protected]#$%^&]).*$
    

Ich habe es getestet und es funktioniert

1
Andrew

Für jeden, der an Mindestanforderungen für jeden Charaktertyp interessiert ist, würde ich vorschlagen, die folgende Erweiterung über die akzeptierte Antwort von Tomalak vorzunehmen:

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

Beachten Sie, dass dies eine Formatierungszeichenfolge ist und nicht das endgültige Regex-Muster. Ersetzen Sie einfach% d durch die minimal erforderlichen Vorkommen für: Ziffern, Kleinbuchstaben, Großbuchstaben, Nicht-Ziffern/-Zeichen und das gesamte Kennwort (jeweils). Maximales Vorkommen ist unwahrscheinlich (es sei denn, Sie möchten eine maximale Anzahl von 0 haben und solche Zeichen effektiv ablehnen), diese könnten jedoch problemlos hinzugefügt werden. Beachten Sie die zusätzliche Gruppierung um jeden Typ, sodass die Min/Max-Einschränkungen nicht aufeinander folgende Übereinstimmungen zulassen. Dies war ein Wunder für ein System, in dem wir zentral konfigurieren konnten, wie viele Zeichen jeder Charaktertyp wir brauchten, und die Website sowie zwei verschiedene mobile Plattformen diese Informationen abrufen konnten, um das Regex-Muster auf der Grundlage der obigen Formatierungszeichenfolge zu erstellen.

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

Erklärung:

  1. Legen Sie zunächst das Kennwort als Zeichenfolge fest und erstellen Sie eine Ganzzahl o.
  2. Überprüfen Sie dann jedes Zeichen anhand der for-Schleife.
  3. Wenn es eine Zahl in der Zeichenfolge findet, fügen Sie die Zahl 5 hinzu. Springen Sie dann zur next-Schleife. Character.isDigit (s.charAt (i))
  4. Diese Schleife überprüft alle in der Zeichenfolge platzierten Alphabete. Wenn es gefunden ist, dann Füge eine weitere 5 in n hinzu. Character.isLetter (s.charAt (i))
  5. Überprüfen Sie nun die ganze Zahl n anhand der if-Bedingung. Wenn n = 10 ist wahr Die angegebene Zeichenfolge ist alphanumerisch, andernfalls nicht.
0
Naresh Babu

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

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

[Regex Demo]

0
shA.t

Java-Methode für Sie bereit, mit Parametern

Einfach kopieren und einfügen und die gewünschten Parameter einstellen.

Wenn Sie kein Modul wünschen, kommentieren Sie es einfach oder fügen Sie ein "wenn" für ein spezielles Zeichen hinzu

//______________________________________________________________________________
/**
 * 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;
}        
0
Fausto70

Auch das können Sie 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;
}
0
RANAJEET BARIK

einfaches

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

  1. (? = irgendwas) -> bedeutet positive Vorwärtssuche in allen Eingabestrings und sicherstellen, dass diese Bedingung geschrieben wird .sample (? =. * [0-9]) -> bedeutet, dass eine Ziffer in den all-String geschrieben wird. wenn nicht geschrieben return false .
  2. (?! irgendwas) -> (umgekehrt) bedeutet negative Vorwärtsschau, wenn Bedingung geschrieben return false ist.

    schließen Bedeutung ^ (Bedingung) (Bedingung) (Bedingung) (Bedingung) [\ S] {8,10} $

0
ibrahem shabban

Dieser prüft für jedes Sonderzeichen:

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