2010-04-06 7 views
4

J'utilise l'expression rationnelle suivante pour valider la complexité du mot de passe:Aide à la complexité du mot de passe regex

/^.*(?=.{6,12})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/ 

En bref: 2 minuscules, 2 majuscules, 2 numéros, longueur min est 6 et la longueur maximale est de 12.

Cela fonctionne parfaitement, sauf pour la longueur maximale, lorsque j'utilise aussi une longueur minimale.

Par exemple:

/^.*(?=.{6,})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/

Cette correctement nécessite une longueur minimale de 6!

Et ceci:

/^.*(?=.{,12})(?=.*[0-9]{2})(?=.*[A-Z]{2})(?=.*[a-z]{2}).*$/ 

nécessite correctement une longueur maximale de 12.

Cependant, quand je les jumeler ensemble comme dans le premier exemple, il ne fonctionne tout simplement pas !!

Ce qui donne? Merci!

+2

une raison particulière pour laquelle vous voulez empêcher quelqu'un d'avoir un mot de passe de plus de 13 caractères (et donc plus sécurisé)? – nickf

+0

Certains systèmes ont en fait une longueur maximale de mot de passe qu'ils peuvent accepter, je me souviens de mon vieux réseau unix/windows combiné à l'uni, nous ne pouvions pas avoir plus de 8 caractères. – hhafez

+0

À moins d'une limitation technique inévitable imposant une limite stricte à la longueur du mot de passe (comme dans la situation de @ hhafez), la meilleure pratique est de ne pas limiter inutilement la longueur du mot de passe (comme l'a dit @nickf). Ce n'est pas comme si vous deviez stocker le mot de passe, de toute façon - seulement son hash, qui est généralement de la même longueur que le mot de passe soit 2 caractères ou 200. –

Répondre

14

Vous voulez:

/^(?=.{6,12}$)... 

Ce que vous faites est de dire: me trouver une séquence de caractères qui est suivie par:

  • 6-12 caractères
  • une autre séquence de caractères suivi de 2 chiffres
  • une autre séquence de caractères suivie de 2 lettres majuscules
  • une autre séquence de caractères qui est suivie par 2 lettres minuscules

Et tout cela est suivi par une autre séquence de caractères. C'est pourquoi la longueur maximale ne fonctionne pas car 30 caractères suivis de 00AAaa et 30 autres caractères vont passer.

Egalement ce que vous faites est de forcer deux nombres ensemble. Pour être moins rigoureux que cela, mais nécessitant au moins deux chiffres partout dans la chaîne:

/^(?=.{6,12}$)(?=(.*?\d){2})(?=(.*?[A-Z]){2})(?=(.*?[a-z]){2})/ 

Enfin, vous remarquerez que je suis en utilisant des expressions non gourmandes (.*?). Cela permettra d'éviter un backtracking et pour ce genre de validation, c'est ce que vous devriez généralement utiliser. La différence entre:

(.*\d){2} 

et

(.*?\d){2} 

Est-ce que le premier va saisir tous les personnages avec .* et ensuite chercher un chiffre. Il n'en trouvera pas car il sera à la fin de la chaîne de sorte qu'il fera marche arrière d'un caractère et cherchera ensuite un chiffre. Si ce n'est pas un chiffre, il va revenir en arrière jusqu'à ce qu'il en trouve un.Après cela, il va correspondre à cette expression une seconde fois, ce qui déclenchera encore plus de retours en arrière.

C'est ce que des caractères génériques gourmands signifie.

La seconde version transmettra 0 caractères au .*? et recherchera un chiffre. Si ce n'est pas un chiffre .*? va saisir un autre caractère, puis chercher un chiffre et ainsi de suite. Particulièrement sur les longues chaînes de recherche, cela peut être plus rapide. Avec un mot de passe court, cela ne fera certainement pas de différence, mais c'est une bonne habitude de savoir comment fonctionne le regex matcher et d'écrire la meilleure regex possible. Cela étant dit, c'est probablement un exemple d'être trop intelligent pour votre propre bien. Si un mot de passe est rejeté comme ne remplissant pas ces conditions, comment déterminez-vous lequel a échoué afin de donner à l'utilisateur des informations sur ce qu'il doit réparer? Une solution programmatique est, dans la pratique, probablement préférable.

+0

excellente réponse, merci pour l'explication aussi! :) –