Regulärer Ausdruck, um zu überprüfen, ob das Passwort "8 Zeichen einschließlich 1 Großbuchstaben, 1 Sonderzeichen, alphanumerische Zeichen" lautet.

102

Ich möchte, dass ein regulärer Ausdruck dies überprüft

Ein Passwort muss aus acht Zeichen bestehen, einschließlich eines Großbuchstabens, eines Sonderzeichens und alphanumerischer Zeichen.

Und hier ist mein Validierungsausdruck für acht Zeichen, einschließlich eines Großbuchstaben, eines Kleinbuchstaben und einer Zahl oder eines Sonderzeichens.

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

Wie kann ich es für ein Passwort schreiben, das aus acht Zeichen bestehen muss, einschließlich eines Großbuchstabens, eines Sonderzeichens und alphanumerischer Zeichen?

Rania Umair
quelle
26
Warum brauchen Sie dafür einen regulären Ausdruck? Ein vollständiger regulärer Ausdruck, der Ihren Anforderungen entspricht, ist sehr lang und komplex. Es ist einfacher, Ihre Einschränkungen in C # -Code zu schreiben.
Greg Hewgill
32
Haben Sie darüber nachgedacht, nach einem sicheren Passwort zu suchen, anstatt zu überprüfen, ob das Passwort einigen willkürlichen Regeln entspricht, die ein unvollständiger Proxy für ein sicheres Passwort sind? Es gibt viele Bibliotheken und Programme, die, wenn sie mit einem Passwort versehen werden, dessen Stärke bestimmen.
Wayne Conrad
4
@ GregHewgill Ich würde Ihren Kommentar positiv bewerten, wenn ich könnte :-) Dies sieht aus wie ein weiterer Fall von "Wenn Sie nur einen Hammer haben, sieht alles wie ein Nagel aus".
Christian.K
3
Benötigen Sie genau einen Großbuchstaben / Sonderzeichen oder mindestens einen?
mmdemirbas
4
Meinen Sie mit den Anforderungen des Benutzers, dass Ihr Benutzer Implementierungsdetails diktiert? Vielleicht sollten sie das dann einfach selbst codieren. Um ehrlich zu sein, denke ich, dass es einfacher zu pflegen und zu verstehen wäre, wenn Sie nur Zähler erstellen und jedes Zeichen einzeln überprüfen und die entsprechenden Zähler für jedes Zeichen erhöhen würden, das einer Regel entspricht. Aus technischer Sicht wird es niemanden beeindrucken, aber warum sollte man Dinge mit etwas komplizieren, das fehleranfällig und schwer zu aktualisieren ist?

Antworten:

132

Der reguläre Ausdruck, nach dem Sie suchen, wird höchstwahrscheinlich riesig und ein Albtraum sein, den Sie besonders für Menschen pflegen müssen, die mit regulären Ausdrücken nicht so vertraut sind.

Ich denke, es wäre einfacher, Ihre Regex zu zerlegen und es Stück für Stück zu tun. Es könnte etwas länger dauern, aber ich bin mir ziemlich sicher, dass es einfacher wäre, es zu warten und zu debuggen. Auf diese Weise können Sie Ihren Benutzern (außer nur Invalid Password) gezieltere Fehlermeldungen zur Verfügung stellen, die die Benutzererfahrung verbessern sollen.

Nach dem, was ich sehe, sprechen Sie Regex ziemlich fließend, daher würde ich davon ausgehen, dass es sinnlos wäre, Ihnen die regulären Ausdrücke zu geben, um das zu tun, was Sie brauchen.

Wenn ich Ihren Kommentar sehe, würde ich so vorgehen:

  • Muss acht Zeichen lang sein: Sie benötigen dafür keinen regulären Ausdruck. Die Nutzung der .LengthEigenschaft sollte ausreichen.

  • Einschließlich eines Großbuchstabens: Sie können den [A-Z]+regulären Ausdruck verwenden. Wenn die Zeichenfolge mindestens einen Großbuchstaben enthält, ergibt dieser reguläre Ausdruck true.

  • Ein Sonderzeichen: Sie können entweder das \WZeichen verwenden, das mit jedem Zeichen übereinstimmt, das kein Buchstabe oder eine Zahl ist, oder Sie können so etwas verwenden [!@#], um eine benutzerdefinierte Liste von Sonderzeichen anzugeben. Beachten Sie aber , dass Charaktere wie $, ^, (und )sind Sonderzeichen in der regulären Ausdruckssprache, so dass sie wie so entkommen sein müssen: \$. Kurz gesagt, Sie könnten das verwenden \W.

  • Alphanumerische Zeichen: Die Verwendung von \w+sollte mit jedem Buchstaben, jeder Zahl und jedem Unterstrich übereinstimmen.

Weitere Informationen finden Sie in diesem Tutorial.

npinti
quelle
2
Ich habe dies nicht selbst geschrieben. Ich bekomme es von Google, liebe Freundin
Rania Umair
4
@RaniaUmair: Ich denke, dass Ihr Kommentar meinen Standpunkt beweist. Ich würde empfehlen, dass Sie es wie angegeben aufschlüsseln.
Npinti
35
+1 Regex ist mächtig, sollte aber kein Problem im Universum lösen
Cristian Lupascu
@ w0lf: Ich könnte nicht mehr zustimmen. Regex ist leistungsstark, wird jedoch zu schnell zu komplex. Halten Sie es also besser einfach.
Npinti
Kannst du mir helfen? Ich brauche einen Regx, der mindestens eine Nummer akzeptiert und maximal 3 andere Charaktere können alles sein
Lijo
107
(                   # Start of group
    (?=.*\d)        #   must contain at least one digit
    (?=.*[A-Z])     #   must contain at least one uppercase character
    (?=.*\W)        #   must contain at least one special symbol
       .            #     match anything with previous condition checking
         {8,8}      #        length is exactly 8 characters
)                   # End of group

In einer Zeile:

((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})

Bearbeiten 2019-05-28:

Sie müssen die gesamte Eingabezeichenfolge abgleichen. Sie können also den regulären Ausdruck zwischen ^und einschließen $, um zu verhindern, dass versehentlich Teilübereinstimmungen als Übereinstimmung mit der gesamten Eingabe angenommen werden:

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

Quellen:

mmdemirbas
quelle
58
Weil es aus 12 Zeichen besteht
mmdemirbas
Eine weitere Bedingung sollte nicht mit einer Ziffer beginnen. Wie kann ich das tun?
Lijo
7
Sie können es mit {8} kürzen, um 8 Zeichen zu entsprechen
Angelo Tricarico
es passt zu $ ​​1eerrrrrrr .. es hat keinen Großbuchstaben.
Shilpi Jaiswal
@ShilpiJaiswal Entweder verwenden Sie ein Flag für Übereinstimmungen, bei denen die Groß- und Kleinschreibung nicht berücksichtigt wird, oder Sie führen eine "Suche" anstelle von "Übereinstimmung" durch. Um sicherzustellen, dass Sie mit der gesamten Eingabezeichenfolge übereinstimmen, können Sie den regulären Ausdruck zwischen ^und einfügen $. Versuchen Sie dies:^((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})$
mmdemirbas
35

So viele Antworten ... alles schlecht!

Reguläre Ausdrücke haben keinen UND-Operator, daher ist es ziemlich schwierig, einen regulären Ausdruck zu schreiben, der gültigen Passwörtern entspricht, wenn die Gültigkeit durch etwas UND etwas anderes UND etwas anderes definiert wird ...

Reguläre Ausdrücke haben jedoch einen ODER-Operator. Wenden Sie daher einfach den Satz von DeMorgan an und schreiben Sie einen regulären Ausdruck , der mit ungültigen Kennwörtern übereinstimmt .

alles mit weniger als 8 Zeichen ODER alles ohne Zahlen ODER alles ohne Großbuchstaben ODER alles ohne Sonderzeichen

So:

^(.{0,7}|[^0-9]*|[^A-Z]*|[a-zA-Z0-9]*)$

Wenn etwas dazu passt, ist es ein ungültiges Passwort.

Matt Timmermans
quelle
3
Wenn das OP genau 8 Zeichen wollte, müssten Sie hinzufügen |.{9,}. +1 für das Konzept
Daniel
Eine großartige und einfache Lösung für die Frage, obwohl ich der Meinung bin, dass ein einzelner regulärer Ausdruck nicht der optimale für das eigentliche Problem ist.
Siderite Zackwehdex
1
Reguläre Ausdrücke tun haben AND - Operatoren, sind sie Look - Ahead / Lookbehind Behauptungen genannt.
relativ
13

Die Antwort ist, keinen regulären Ausdruck zu verwenden. Dies ist Sätze und Zählen.

Bei regulären Ausdrücken geht es um Ordnung.

In Ihrem Leben als Programmierer werden Sie gebeten, viele Dinge zu tun, die keinen Sinn ergeben. Lerne ein Level tiefer zu graben. Erfahren Sie, wenn die Frage falsch ist.

Die Frage (wenn es um reguläre Ausdrücke geht) ist falsch.

Pseudocode (hat in letzter Zeit zwischen zu vielen Sprachen gewechselt):

if s.length < 8:
    return False
nUpper = nLower = nAlphanum = nSpecial = 0
for c in s:
    if isUpper(c):
        nUpper++
    if isLower(c):
        nLower++
    if isAlphanumeric(c):
        nAlphanum++
    if isSpecial(c):
        nSpecial++
return (0 < nUpper) and (0 < nAlphanum) and (0 < nSpecial)

Ich wette, Sie haben den obigen Code fast sofort gelesen und verstanden. Ich wette, Sie haben mit dem regulären Ausdruck viel länger gebraucht und sind sich weniger sicher, ob er korrekt ist. Die Erweiterung des regulären Ausdrucks ist riskant. Erweitert das Unmittelbare oben, geschweige denn.

Beachten Sie auch, dass die Frage ungenau formuliert ist. Ist der Zeichensatz ASCII oder Unicode oder ?? Meine Vermutung beim Lesen der Frage ist, dass mindestens ein Kleinbuchstabe angenommen wird. Daher denke ich, dass die angenommene letzte Regel lauten sollte:

return (0 < nUpper) and (0 < nLower) and (0 < nAlphanum) and (0 < nSpecial)

(Wenn Sie die Hüte auf sicherheitsorientiert ändern, ist dies eine wirklich ärgerliche / nicht nützliche Regel.)

Zu wissen, wann die Frage falsch ist, ist massiv wichtiger als kluge Antworten. Eine kluge Antwort auf die falsche Frage ist fast immer falsch.

Preston L. Bannister
quelle
2
Genau. Je mehr Leute Sie arbeiten, desto mehr Code muss lesbar sein, obwohl einige Regexp-Implementierungen, die ich als Antworten sah, ziemlich klar sind
Nicola Peluchetti
Ich finde es gut, dass einige Benutzer wie Sie den Mut haben zu sagen, dass Regex nicht immer eine bessere Lösung für die Anwendung ist und dass einfache Programmierung manchmal besser lesbar ist.
Schlebe
12

Als Beispiel, wie dies mit einem lesbaren / wartbaren regulären Ausdruck geschehen könnte.

Für eine längere Regex sollten Sie immer RegexOptions.IgnorePatternWhitespaceLeerzeichen und Kommentare im Ausdruck zulassen, um die Lesbarkeit zu verbessern.

String[] passwords = { "foobar", "Foobar", "Foobar1", "Fooobar12" };

foreach (String s in passwords) {

    Match password = Regex.Match(s, @"
                                      ^              # Match the start of the string
                                       (?=.*\p{Lu})  # Positive lookahead assertion, is true when there is an uppercase letter
                                       (?=.*\P{L})   # Positive lookahead assertion, is true when there is a non-letter
                                       \S{8,}        # At least 8 non whitespace characters
                                      $              # Match the end of the string
                                     ", RegexOptions.IgnorePatternWhitespace);

    if (password.Success) {
        Console.WriteLine(s + ": valid");
    }
    else {
        Console.WriteLine(s + ": invalid");
    }
}

Console.ReadLine();
Stema
quelle
Dies ist der beste Weg, um das lookahead assertionMuster als "und" zu missbrauchen , um die gesamte Einschränkung innerhalb eines einzelnen regulären Ausdrucks abzudecken. Funktioniert für mehr Einschränkungen und kann leicht generiert werden, wenn einige Einschränkungen durch Konfiguration aktiviert / deaktiviert werden sollen.
Dognose
2
Die Verwendung von Unicode-Kategorien ist eine hervorragende Idee. Die Welt ist breiter als ASCII!
Walter Tross
1

Wenn Sie nur einen Großbuchstaben und ein Sonderzeichen benötigen, sollte dies funktionieren:

@"^(?=.{8,}$)(?=[^A-Z]*[A-Z][^A-Z]*$)\w*\W\w*$"
user1096188
quelle
Die Zeichenfolge AAaaaaaaa#ist nach diesem Ausdruck nicht in Ordnung
Cristian Lupascu
3
Nun, es ist 10, nicht 8 Zeichen lang und enthält mehr als einen Großbuchstaben, so dass es fehlschlagen sollte ...
user1096188
4
Sie haben Recht, das steht in der Frage. Ich dachte, diese Regeln wären eher "mindestens ein Großbuchstabe" als "genau ein Großbuchstabe" . Ich bin mir nicht sicher, ob das OP das wollte.
Cristian Lupascu
1

Der reguläre Ausdruck, nach dem Sie gesucht haben, lautet: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*\[\]"\';:_\-<>\., =\+\/\\]).{8,}$/u .

Beispiel und Test: http://regexr.com/3fhr4

Lucas Silva
quelle
Plätze
1
@sniels Ändere einfach das .vor dem {8,}zu [^\s].
Lucas Silva
0

Diese Frage beginnt viral zu werden und es erschienen viele interessante Vorschläge.

Ja, das Schreiben von Hand ist schwierig. Eine einfachere Lösung ist die Verwendung einer Vorlage. Obwohl der resultierende reguläre Ausdruck möglicherweise nicht optimal ist, ist er einfacher zu warten und / oder zu ändern, und der Benutzer hat eine bessere Kontrolle über das Ergebnis. Es ist möglich, dass ich etwas verpasst habe, daher ist jede konstruktive Kritik hilfreich.

Diese Links könnten interessant sein: Ordnen Sie mindestens 2 Ziffern und 2 Buchstaben in beliebiger Reihenfolge in einer Zeichenfolge zu , Sprache für reguläre Ausdrücke , Erfassungsgruppen

Ich verwende diese Vorlage (?=(?:.*?({type})){({count})})basierend auf dem gesamten regulären Ausdruck, den ich in SO gesehen habe. Der nächste Schritt ist das Ersetzen des erforderlichen Musters ( number, special character...) und das Hinzufügen einer Konfiguration für die Länge.

Ich habe eine kleine Klasse zum Erstellen des regulären Ausdrucks PasswordRegexGenerator.cs erstellt. Ein Beispiel:

string result = new PasswordRegexGenerator ( )
        .UpperCase ( 3, -1 )    // ... {3,}
        .Number ( 2, 4 )        // ... {2,4}
        .SpecialCharacter ( 2 ) // ... {2}
        .Total ( 8,-1 )
        .Compose ( );

/// <summary>
/// Generator for regular expression, validating password requirements.
/// </summary>
public class PasswordRegexGenerator
{
    private string _elementTemplate = "(?=(?:.*?({type})){({count})})";

    private Dictionary<string, string> _elements = new Dictionary<string, string> {
        { "uppercase", "[A-Z]" },
        { "lowercase", "[a-z]" },
        { "number", @"\d" },
        { "special", @"\W" },
        { "alphanumeric", @"\w" }
    };

    private StringBuilder _sb = new StringBuilder ( );

    private string Construct ( string what, int min, int max )
    {
        StringBuilder sb = new StringBuilder ( _elementTemplate );
        string count = min.ToString ( );

        if ( max == -1 )
        {
            count += ",";
        }
        else if ( max > 0 )
        {
            count += "," + max.ToString();
        }

        return sb
            .Replace ( "({type})", what )
            .Replace ( "({count})", count )
            .ToString ( );
    }

    /// <summary>
    /// Change the template for the generation of the regex parts
    /// </summary>
    /// <param name="newTemplate">the new template</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexTemplate ( string newTemplate )
    {
        _elementTemplate = newTemplate;
        return this;
       }

    /// <summary>
    /// Change or update the regex for a certain type ( number, uppercase ... )
    /// </summary>
    /// <param name="name">type of the regex</param>
    /// <param name="regex">new value for the regex</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexElements ( string name, string regex )
    {
        if ( _elements.ContainsKey ( name ) )
        {
            _elements[ name ] = regex;
        }
        else
        {
            _elements.Add ( name, regex );
        }
        return this;
    }

    #region construction methods 

    /// <summary>
    /// Adding number requirement
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public PasswordRegexGenerator Number ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "number" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator UpperCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "uppercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator LowerCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "lowercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator SpecialCharacter ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "special" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator Total ( int min, int max = 0 )
    {
        string count = min.ToString ( ) + ( ( max == 0 ) ? "" : "," + max.ToString ( ) );
        _sb.Append ( ".{" + count + "}" );
        return this;
    }

    #endregion

    public string Compose ()
    {
        return "(" + _sb.ToString ( ) + ")";
    }
}
Bakudan
quelle
0

Sie können die folgende Klasse zur Validierung verwenden:

public class PasswordValidator{

  private Pattern pattern;
  private Matcher matcher;

  private static final String PASSWORD_PATTERN =
          "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})";

  public PasswordValidator(){
      pattern = Pattern.compile(PASSWORD_PATTERN);
  }

  /**
   * Validate password with regular expression
   * @param password password for validation
   * @return true valid password, false invalid password
   */
  public boolean validate(final String password){

      matcher = pattern.matcher(password);
      return matcher.matches();

  }
}

Dabei sind 6 und 20 die minimale und maximale Länge für das Passwort.

Amit Pandya
quelle
0
  • Verwenden Sie einen Nonbacktracking-Ausdruck, um zuerst das gesamte Kennwort abzugleichen, wenn es mindestens 8 Zeichen enthält (auf diese Weise gibt es keine kombinatorische Explosion für lange, aber ungültige Kennwörter): (?>{8,})
  • Verwenden Sie Lookbehind-Zusicherungen, um zu überprüfen, ob alle erforderlichen Zeichen (UND-Bedingungen) vorhanden sind. (?<=...)
  • Mindestens ein Großbuchstabe: (?<=\p{Lu}.*)
  • Mindestens ein Sonderzeichen (etwas mehrdeutig, aber verwenden wir kein Wort): (?<=\W.*)
  • Mindestens ein alphanumerisches Zeichen (: (?<=\w.*)

Zusammenfassend:

(?>.{8,})(?<=\p{Lu}.*)(?<=\W.*)(?<=\w.*)

relativ zufällig
quelle
0

Am besten ist es, nicht für alles Regex zu verwenden. Diese Anforderungen sind sehr gering. Bei CPU-bezogenen Zeichenfolgen sind Operationen zur Überprüfung der Kriterien / Validierung viel billiger und schneller als Regex!

ANS
quelle
-2
/^(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}$/
Kailash Karki
quelle
15
Ich schlage vor, dass Sie Ihre Frage bearbeiten und eine Erklärung hinzufügen. Nur-Code-Antworten sind manchmal gut genug, aber Code + Erklärungsantworten sind immer besser
Barranka