2010-04-14 19 views
17

Ho visto la seguente espressione regolare in tutto il web.Espressione regolare PHP per validazione password sicura

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

Si convalida solo se la stringa:

* contain at least (1) upper case letter 
    * contain at least (1) lower case letter 
    * contain at least (1) number or special character 
    * contain at least (8) characters in length 

Mi piacerebbe sapere come convertire questa espressione regolare in modo che controlla la stringa da

* contain at least (2) upper case letter 
* contain at least (2) lower case letter 
* contain at least (2) digits 
* contain at least (2) special character 
* contain at least (8) characters in length 

Beh, se contiene almeno 2 caratteri in alto, in basso, cifre e caratteri speciali, quindi non vorrei che gli abbiano la lunghezza di 8 caratteri.

caratteri speciali includono:!.?

`~ @ # $%^& *() _- + = [] \ | {} ;: '",/<>

+2

Si prega di definire il carattere * speciale *. Intendi solo: '! @ # $%^& *() -_ = + [{]} ;: '", <.> /? 'O forse qualcosa di più? – Crozin

+0

ha aggiornato la domanda con il set di caratteri speciali – Jason

+4

Don non odi quei siti web che limitano la complessità delle password "per motivi di sicurezza?" Vuoi impostare ".evmhcfcyK" (facile da ricordare perché proviene da una frase) e finisci con "abcd1234" scritto in un post-it Nota: –

risposta

31

Il modo migliore per adattare la regex è quello di estrapolarlo e scrivere un po 'di codice: la regex richiesta sarebbe lunga e complicata, non sarebbe possibile leggerla due ore dopo averla scritta. sarà noioso, ma almeno riuscirai a capire cosa hai scritto

Questo non è uno schianto su di te, a proposito. I regex sono appena sufficienti per la convalida della password in molti casi, ma i tuoi requisiti sono più complicati del solito e non ne vale la pena. Inoltre, la regex che hai postato è una schifezza. Non fidarti mai delle regex che trovi fluttuanti nel web. O qualsiasi codice, se è per questo. Oppure, diamine, nulla. : -/

+3

Sono d'accordo, è meglio eseguire controlli separati e non una regex magica, in questo modo puoi facilmente modificare parti specifiche o aggiungerle/rimuoverle Personalmente non credo che forzare una password sicura sia una buona esperienza utente, quelle basate su JS le barre di "sicurezza delle password" sono molto migliori perché entrambi istruiscono l'utente e li puniscono leggermente per l'uso di una password errata, ma se vogliono davvero usarne uno, possono. – TravisO

+0

ok ok .. mi persuadono tutti .. Io non proverò la regex poiché è chiaramente illeggibile, grazie a tutti e! – Jason

+0

@TravisO: Sì, mi piacciono anche quelle barre di sicurezza delle password. –

16

Se davvero si vuole usare un'espressione regolare, provate questo:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$ 

Qualche spiegazione:

  • (?=^(?:[^A-Z]*[A-Z]){2}) test per due ripetizioni di [^A-Z]*[A-Z] che è una sequenza di zero o più caratteri tranne lettere maiuscole seguite da una lettera maiuscola
  • (?=^(?:[^a-z]*[a-z]){2}) (come sopra con lettere minuscole)
  • (?=^(?:\D*\d){2}) (come sopra con cifre)
  • (?=^(?:\w*\W){2}) (come sopra con caratteri non di parola, ma si può cambiare \W con una classe di caratteri di qualsiasi caratteri speciali che si desidera)
  • ^[A-Za-z\d\W]{8,}$ mette alla prova la durata di tutta la stringa che consiste solo di carattere dell'unione di tutte le altre classi di caratteri.
+0

Ottima risposta con una bella spiegazione, la voterò anche se non raccomando la tua risposta. In questo caso penso che stia diventando illeggibile, il codice standard sarebbe una scelta migliore, l'unica ragione per cui userei regex perché le prestazioni estreme erano un problema e avevo bisogno di controllare milioni di password. – TravisO

+1

In realtà, se le prestazioni fossero un fattore, sarebbe un altro motivo * non * per usare un'espressione regolare. Altrimenti concordo: +1 per la soluzione regex definitiva (nel caso in cui devi davvero seguire quella strada). –

+0

+1 Invece di fornire una lunga regex non leggibile in formato nativo (e una spiegazione separata), è molto meglio (e meno lavoro) scrivere la regex in modalità di spaziatura libera dal get-go, completa di indentazione corretta e commenti generosi. Un ulteriore vantaggio è che una regex verbosa auto-documentante e libera la modalità è molto più mantenibile in futuro. – ridgerunner

62

Sono d'accordo con Alan. Se la regex esistente è così complicata, perché provare a farlo in una sola regex?

Basta scomporlo in semplici passi accessibili. L'hai già fatto.

Ora scrivere 4 regex per convalidare le parti, aggiungere la logica di base alle 4 regex e misurare la lunghezza della stringa. Fatto.

Cosa sarebbe preferibile eseguire il debug, questo:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$ (che non funziona btw ...)

o questo:

function valid_pass($candidate) { 
    $r1='/[A-Z]/'; //Uppercase 
    $r2='/[a-z]/'; //lowercase 
    $r3='/[[email protected]#$%^&*()\-_=+{};:,<.>]/'; // whatever you mean by 'special char' 
    $r4='/[0-9]/'; //numbers 

    if(preg_match_all($r1,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r2,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r3,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r4,$candidate, $o)<2) return FALSE; 

    if(strlen($candidate)<8) return FALSE; 

    return TRUE; 
} 

Perché la gente sentono di dover scrivere un regex che nessuno può capire solo per poterlo fare in una volta sola è oltre me ...


Ok ok - se vuoi davvero una singola regex, scopri lookaheads per convalidare le tue regole.

Questo mostro fa quello che hai chiesto in un colpo solo:

^          # start of line 
(?=(?:.*[A-Z]){2,})      # 2 upper case letters 
(?=(?:.*[a-z]){2,})      # 2 lower case letters 
(?=(?:.*\d){2,})       # 2 digits 
(?=(?:.*[[email protected]#$%^&*()\-_=+{};:,<.>]){2,}) # 2 special characters 
(.{8,})         # length 8 or more 
$          # EOL 

Demo

+0

Mi piace questa soluzione; bello e chiaro cosa sta succedendo pur essendo ragionevolmente conciso. +1 – andrhamm

+0

@andrhamm Esiste un modo per connettere le prime due linee? Caratteri superiori o inferiori non superiori e inferiori? – Byakugan

+0

@Byakugan prova $ r1 = '/ [A-Za-z] /'; // Maiuscolo o minuscolo – andrhamm