2016-06-03 10 views
1

konstruiere Ich muss einen Login-Namen überprüfen. Es muss (es ist politische, nicht technische Entscheidung) haben:Wie man spezifische Java regexp

  1. von 5 bis 30 Zeichen;
  2. Zeichen müssen aus Gruppe [a-zA-Z0-9*] stammen;
  3. Mindestens ein Zeichen muss Nummer sein;
  4. Es ist nicht möglich, alle Zeichen nur aus Zahlen zu haben, wenn der Anmeldename 5 Zeichen hat, aber wenn er 6 oder mehr Zeichen hat, kann er nur aus Zahlen bestehen.

Ich habe regexp (?=[a-zA-Z0-9*]*[0-9])[a-zA-Z0-9*]{5,30} wich für Punkte arbeitet 1-3, aber kann sich nicht vorstellen, wie Scheck sind für Punkt 4.

+1

Wenn Sie dies nur in Java tun, warum nicht einfach ein if/else verwenden, um dies in 2 Regexes basierend auf einer Anzahl von Zeichen zu brechen? Es ist technisch möglich und ich versuche, es jetzt hochzupeitschen ... –

+1

Sie könnten einen Look-behing wie '(?! [0-9] {5} $)' –

+0

@SebastianProske hinzufügen, der Sequenzen von 5 nicht erlauben würde Ziffern am Ende, aber was ist, wenn das Passwort etwas wie 'a12345' ist? – Thomas

Antwort

1

Es ist immer verlockend, alle Aspekte eines Strings mit einem einzigen, ziemlich komplizierten regulären Ausdruck zu überprüfen. Aber denken Sie daran, dass diese Sache schwer zu erweitern und in Zukunft aufrechtzuerhalten ist.

Bedeutung: Abhängig von der Rate der "Änderungen" Ihrer Validierungsregeln könnte es bessere Designs geben. Zum Beispiel könnte man so etwas wie vorstellen:

interface NameValidator { 
    isValid(String name) throws InvalidNameException; 
} 

class LengthValidator implements NameValidator ... 
class XyzValidator implements NameValidator ... 

class NameValidation { 
    private final List validators = Arrays.toList(new LengthValidator(), ... 

    void isValid(String name) { 
     run all validators ... 

Auf diese Weise, das Hinzufügen/Ändern einer Ihrer Validierungsregeln ... wird viel mehr geradlinig ... als einen einzigen regulären Ausdruck Manipulation, möglicherweise einen anderen Teil zu brechen davon.

Darüber hinaus können Sie sogar unterschiedliche Regelwerke erstellen; durch Kombinieren verschiedener Instanzen von NameValidation-Implementierern; unter Vermeidung von Code-Duplizierung.

0

Wie andere darauf hingewiesen haben, müssen Sie es nicht mit einem einzigen Regex machen. Selbst wenn das möglich ist, wird es für andere unverständlich komplex und schwierig zu verstehen sein.

Der einfachste Ansatz ist die beste:

boolean passwordValid = password.matches("[a-zA-Z0-9*]{5,30}") 
    && password.matches(".*[0-9].*") 
    && !password.matches("[0-9]{5}"); 
+0

Man könnte einen Schritt weiter gehen, jedes Spiel neu zu factor in seine eigene Methode .... – GhostCat

0

Ich möchte einen anderen Ansatz vorschlagen: keine Regex verwenden, aber jedes Zeichen überprüfen und Passwort Eigenschaften zu sammeln. Auf diese Weise können Sie später komplexere Anforderungen implementieren, z. "Es muss 3 von 4 haben".

Beispiel:

String pw = "1a!cde"; 

Set<PwProperty> passwordProperties = new HashSet<>(); 
for(char c : pw.toCharArray()) { 
    if(isDigit(c)) { 
    passwordProperties.add(PwProperty.DIGIT); 
    } 
    else if (isSpecialChar(c)) { 
    passwordProperties.add(PwProperty.SPECIAL); 
    } 
    else if(isUpperCase(c)) { 
    passwordProperties.add(PwProperty.UPPER_CASE); 
    } 
    else if(isLowerCase(c)) { 
    passwordProperties.add(PwProperty.LOWER_CASE); 
    } 
    else { 
    passwordProperties.add(PwProperty.UNKNOWN); 
    } 
} 

Dann könnten Sie, dass wie diese (Pseudocode):

if(!pw.length() in range) { 
    display "password too short" or "password too long" 
} 

if(passwordProperties.contains(PwProperty.UNKNOWN) { 
    display "unsupported characters used" 
} 

Set<PwProperty> setOf4 = { DIGIT, SPECIAL, LOWER_CASE, UPPER_CASE } 
if(intersection(passwordProperties, setOf4).size() < 3) { 
    display "use at least 3 out of 4" 
} 

if(!passwordProperties.contains(DIGIT)) { 
    display "must contain digits" 
} 

display "password strength" being intersection(passwordProperties, setOfGoodProperties).size() 

etc. 

Dies kann dann beispielsweise erweitert werden mit Eigenschaften wie DIGIT_SEQUENCE, die unerwünscht sein könnten usw.

Der Hauptvorteil besteht darin, dass Sie detailliertere Informationen zum Kennwort haben, als "es entspricht einer bestimmten Regex oder nicht", und Sie können diese Informationen verwenden, um den Benutzer zu führen.

+0

sollte es ein Problem geben, falls Sie Regex in der Konfigurationsdatei – 1ac0

+0

@LadislavDANKO verwenden müssen, das stimmt und das könnte ein Grund sein, diesen Ansatz nicht zu verwenden. Dies soll jedoch, insbesondere bei der Benutzerführung, mehr Flexibilität bieten und dennoch so implementiert werden, dass eine Konfiguration über eine Textdatei möglich ist. – Thomas

Verwandte Themen