2013-10-03 11 views
5

Sono abbastanza nuovo per Regex, ho appena iniziato a impararlo a scuola. Ho ottenuto il mio primo incarico e sto attraversandolo abbastanza bene.Validate Min/Max length of Password

Lasciatemi spiegare in modo che il mio codice abbia senso ... L'assegnazione sta effettuando la ricerca .NET Regex Tester tramite un testo per le password. Queste password non possono contenere spazi bianchi (così ho usato \S) non può iniziare con un numero o di sottolineatura, quindi ho usato (?m:^([^_|^0-9]{1}) non può finire su due personaggi diversi

(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>) 

deve contenere almeno un cifra, quindi ho usato un lookahead. Ora, la cosa qui è, il codice è una cosa abbastanza ingombra in questo momento.

(?=.*\d)(?m:^([^_|^0-9]{1})(\S*)(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>)) 

E devo aggiungere ancora una cosa, la password deve essere lunga da 8 a 20 caratteri. So che devo usare {8,20} (credo), ma il fatto è che, non importa dove io inserisco questo, uccide completamente la ricerca.

Qualcuno ha un'idea di come posso risolvere questo?

Molto apprezzato.

risposta

1

[Disclaimer, che è una risposta piuttosto lunga!]

ho inizierà con il limite di caratteri.

Dovrete usare (?<!\S) e (?!\S) per indicare l'inizio e la fine della password e utilizzare \S{8,20} per la password effettiva:

(?m)(?<!\S)\S{8,20}(?!\S) 

Come probabilmente già sapete (?m) è per multilinea (^ e $ corrisponde all'inizio e alla fine della riga invece della stringa in questa modalità).

(?<!\S) assicura che non ci sia un carattere non di spazi vuoti prima della password.

(?!\S) assicura che non ci sia un carattere non di spazio vuoto dopo la password.

Ora aggiungiamo alcune restrizioni:

non possono iniziare con un numero o di sottolineatura: (?![0-9_]) un lookahead negativo all'inizio della password:

(?m)(?<!\S)(?![0-9_])\S{8,20}(?!\S) 

deve contenere almeno una cifra: (?=\S+[0-9]) un lookahead positivo al via della password:

(?m)(?<!\S)(?![0-9_])(?=\S+[0-9])\S{8,20}(?!\S) 

devono terminare con gli stessi caratteri: dovrete catturare la seconda d per durare il carattere e usare un backreference. È possibile modificare la parte \S{8,20}-\S{6,18}(\S)\1 per questo:

(?m)(?<!\S)(?![0-9_])(?=\S+[0-9])\S{6,18}(\S)\1(?!\S) 

Ora che dovrebbe essere buona.


Per il tuo regex ora:

(?m:^([^_|^0-9]{1}) 

In primo luogo, il {1} ​​è ridondante, perché se si rimuove, non cambierebbe nulla.

(?m:^([^_|^0-9]) 

In secondo luogo, si hanno parentesi squilibrate. Non sono sicuro di cosa dovrebbe essere, ma immagino che il primo paren non sia stato pensato.

(?m:^[^_|^0-9]) 

Avanti, la classe di caratteri [^_|^0-9] corrisponde a qualsiasi carattere ad eccezione _, |, ^ o la gamma 0-9. Sono sicuro che una password può iniziare con | o ^. Il metacarattere | perde il suo significato in una classe di caratteri! È possibile utilizzare questo: [^_0-9] invece e questo sarebbe diventato:

(?m:^[^_0-9]) 

E 'bene utilizzare questo, ma si dovrà tenere a mente che questo è il primo carattere nella password; perché hai un range di 8 o 20 caratteri da rispettare, e è appena cambiato in 7,19. L'unica cosa che rimane è che accetta anche uno spazio.Si può mettere uno nella classe del personaggio per evitare questo:

(?m:^[^_0-9 ]) 

Va bene, sembra meglio ora, prossimo:

(?<finalTwo>(?i:\S{1}))(?i:\<finalTwo>) 

primo è un gruppo di cattura di nome, va bene, con un gruppo non-capture con la modalità di insensibilità del caso attivata (non del tutto necessaria poiché non abbiamo alfabeti nella regex) e \S{1} all'interno di quel gruppo non di acquisizione. Ancora una volta, lo {1} è ridondante. La rimozione e la modalità (?i), questo diventa:

(?<finalTwo>\S)(?:\<finalTwo>) 

Che non è così male, se corrisponde l'ultimo due caratteri, che sarà realmente il loro lavoro.

(?=.*\d) 

Funziona bene. Potresti voler cercare i personaggi diversi da \d corrispondenze, ad esempio \d, ma se non ti dispiace, questo funziona quasi; sarebbe meglio usare \S invece di . qui nel caso in cui ci siano due password separate da uno spazio l'una accanto all'altra nel testo e questo potrebbe rendere le cose non come volevi.

(\S*) 

Questa parte è più o meno ok. Non c'è alcun limite imposto.

(?=\S*\d)(?m:^[^_0-9 ])(\S*)(?<finalTwo>\S)(?:\<finalTwo>) 

Okay, ora, ricordate che (?m:^[^_0-9]) ha preso un carattere, e (?<finalTwo>\S)(?:\<finalTwo>) prende due personaggi, per un totale di 3. Il limite si impongono dunque è:

(?=\S*\d)(?m:^[^_0-9 ])(\S{5,17})(?<finalTwo>\S)(?:\<finalTwo>) 

Funziona quasi, e si solo bisogno di mettere qualcosa per impedire la corrispondenza parziale di password più lunghe. Di solito puoi utilizzare i limiti di parole \b ma non è stato menzionato nulla sui simboli, quindi è più sicuro presumere che sia consentita anche una password come [email protected]*&AUn++ ed è qui che i limiti di parola falliranno. Ecco perché suggerisco l'uso dei lookaround negativi.

0

Come circa la seguente:

^(?!^[^0-9]+$)[^0-9_].{5,17}(.)\1$ 

^: start-of-stringa.

(?!^[^0-9]+$): assicurarsi che ci sia una cifra assicurandosi che la password non sia solo una combinazione di caratteri non numerici.

[^0-9_]: assicurarsi che inizi con qualcosa che non sia una cifra o un trattino basso.

.{5,17}: corrisponde a qualsiasi carattere tra 5 e 17 volte.

(.): corrispondere il carattere poco prima l'ultimo, e catturare in gruppo 1.

\1: Assicurarsi che l'ultimo carattere è lo stesso di quello precedente.

$: Fine stringa.

[^0-9_], (.) e \1 occupano 3 caratteri, questo lascia 5 caratteri come minimo per .{5,17} e quindi la 5 come confine minimo, e quindi 17 come il limite superiore che rende un totale massimo di 20 caratteri.

Regex101 Demo

So che la demo utilizza PHP, ma in realtà non importa qui.