web-dev-qa-db-fra.com

Expression régulière pour la validation du mot de passe

J'utilise actuellement cette expression régulière pour vérifier si une chaîne est conforme à quelques conditions.

Les conditions sont Chaîne doit comporter entre 8 et 15 caractères. chaîne doit contenir au moins un nombre. La chaîne doit contenir au moins une lettre majuscule. La chaîne doit contenir au moins une lettre minuscule. 

(?!^[0-9]*$)(?!^[a-zA-Z]*$)^([a-zA-Z0-9]{8,15})$

Cela fonctionne pour la plupart, mais ne permet pas le caractère spécial. Toute aide permettant de modifier cette expression rationnelle pour permettre un caractère spécial est très appréciée.

43
desi

Il semble y avoir beaucoup de confusion ici. Les réponses que je vois jusqu'à présent n'appliquent pas correctement la règle 1+ nombre/1 + minuscule/1 + majuscule, ce qui signifie que des mots de passe tels que abc123, 123XYZ ou AB * & ^ # serait toujours accepté. Empêcher les minuscules, les majuscules ou tous les chiffres ne suffit pas; vous devez imposer la présence d'au moins un de chacun.

Essayez ce qui suit:

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

Si vous souhaitez également exiger au moins un caractère spécial (ce qui est probablement une bonne idée), essayez ceci:

^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[^\da-zA-Z]).{8,15}$

Le .{8,15} peut être rendu plus restrictif si vous le souhaitez (par exemple, vous pouvez le changer en \S{8,15} pour interdire les espaces), mais n'oubliez pas que cela réduira la force de votre jeu de mots de passe.

J'ai testé ce modèle et il fonctionne comme prévu. Testé sur ReFiddle ici: http://refiddle.com/110


Edit: Une petite note, le easiest moyen de le faire est d'utiliser 3 expressions rationnelles distinctes et la propriété Length de la chaîne. C'est aussi plus facile à lire et à maintenir, alors faites-le ainsi si vous en avez la possibilité. S'il s'agit de règles de validation dans le balisage, vous êtes probablement bloqué avec une seule expression régulière.

79
Justin Morgan

Une expression régulière est-elle un moyen plus facile/meilleur d'appliquer une contrainte simple qu'un moyen plus évident?

static bool ValidatePassword( string password )
{
  const int MIN_LENGTH =  8 ;
  const int MAX_LENGTH = 15 ;

  if ( password == null ) throw new ArgumentNullException() ;

  bool meetsLengthRequirements = password.Length >= MIN_LENGTH && password.Length <= MAX_LENGTH ;
  bool hasUpperCaseLetter      = false ;
  bool hasLowerCaseLetter      = false ;
  bool hasDecimalDigit         = false ;

  if ( meetsLengthRequirements )
  {
    foreach (char c in password )
    {
      if      ( char.IsUpper(c) ) hasUpperCaseLetter = true ;
      else if ( char.IsLower(c) ) hasLowerCaseLetter = true ;
      else if ( char.IsDigit(c) ) hasDecimalDigit    = true ;
    }
  }

  bool isValid = meetsLengthRequirements
              && hasUpperCaseLetter
              && hasLowerCaseLetter
              && hasDecimalDigit
              ;
  return isValid ;

}

Selon vous, lequel des programmeurs de maintenance dans 3 ans qui doit modifier la contrainte comprendra mieux?

40
Nicholas Carey

Vous pouvez essayer cette méthode:

private bool ValidatePassword(string password, out string ErrorMessage)
    {
        var input = password;
        ErrorMessage = string.Empty;

        if (string.IsNullOrWhiteSpace(input))
        {
            throw new Exception("Password should not be empty");
        }

        var hasNumber = new Regex(@"[0-9]+");
        var hasUpperChar = new Regex(@"[A-Z]+");
        var hasMiniMaxChars = new Regex(@".{8,15}");
        var hasLowerChar = new Regex(@"[a-z]+");
        var hasSymbols = new Regex(@"[!@#$%^&*()_+=\[{\]};:<>|./?,-]");

        if (!hasLowerChar.IsMatch(input))
        {
            ErrorMessage = "Password should contain At least one lower case letter";
            return false;
        }
        else if (!hasUpperChar.IsMatch(input))
        {
            ErrorMessage = "Password should contain At least one upper case letter";
            return false;
        }
        else if (!hasMiniMaxChars.IsMatch(input))
        {
            ErrorMessage = "Password should not be less than or greater than 12 characters";
            return false;
        }
        else if (!hasNumber.IsMatch(input))
        {
            ErrorMessage = "Password should contain At least one numeric value";
            return false;
        }

        else if (!hasSymbols.IsMatch(input))
        {
            ErrorMessage = "Password should contain At least one special case characters";
            return false;
        }
        else
        {
            return true;
        }
    }
8
Anurag

Je pense que ça devrait être comme ça:

(?!^[0-9]*$)(?!^[a-zA-Z]*$)^(.{8,15})$

Ceci vérifie les contraintes avec vos classes de personnage, puis vérifie si vous avez entre 8 et 15 caractères. Quels personnages n'ont plus d'importance, car vous avez déjà vérifié que vos contraintes correspondent bien.

3
Daniel Hilgarth

Je les vérifierais un par un; c’est-à-dire que vous cherchez un nombre \d+. Si cela échoue, vous pouvez indiquer à l’utilisateur qu’il doit ajouter un chiffre. Cela évite de renvoyer une erreur "Invalid" sans donner à l'utilisateur le sentiment qu'il a tort.

2
Alex K.

Essayez ceci (aussi corrigé vérification pour les majuscules et les minuscules, il y avait un bogue puisque vous les avez regroupés comme [a-zA-Z] il ne cherche qu’au moins un grave ou un supérieur. Alors séparez-les):

(?!^[0-9]*$)(?!^[a-z]*$)(?!^[A-Z]*$)^(.{8,15})$

Mise à jour: j'ai trouvé que la regex ne fonctionne pas vraiment comme prévu et ce n'est pas comme ça qu'elle est censée être écrite aussi!

Essayez quelque chose comme ça:

(?=^.{8,15}$)(?=.*\d)(?=.*[A-Z])(?=.*[a-z])(?!.*\s).*$

(Entre 8 et 15 inclus, contient au moins un chiffre, au moins une majuscule et au moins une minuscule et aucun espace.)

Et je pense que c'est aussi plus facile à comprendre.

2
manojlds

Long, et pourrait peut-être être raccourci. Prend en charge les caractères spéciaux ?"-_.

\A(?=[-\?\"_a-zA-Z0-9]*?[A-Z])(?=[-\?\"_a-zA-Z0-9]*?[a-z])(?=[-\?\"_a-zA-Z0-9]*?[0-9])[-\?\"_a-zA-Z0-9]{8,15}\z
0
Ken White

Merci Nicolas Carey. J'allais utiliser regex d'abord mais ce que vous avez écrit m'a changé d'avis. C'est tellement plus facile à maintenir de cette façon.

//You can set these from your custom service methods
int minLen = 8;
int minDigit 2;
int minSpChar 2;

Boolean ErrorFlag = false;
//Check for password length
if (model.NewPassword.Length < minLen)
{
    ErrorFlag = true;
    ModelState.AddModelError("NewPassword", "Password must be at least " + minLen + " characters long.");
}

//Check for Digits and Special Characters
int digitCount = 0;
int splCharCount = 0;
foreach (char c in model.NewPassword)
{
    if (char.IsDigit(c)) digitCount++;
    if (Regex.IsMatch(c.ToString(), @"[!#$%&'()*+,-.:;<=>?@[\\\]{}^_`|~]")) splCharCount++;
}

if (digitCount < minDigit)
{
    ErrorFlag = true;
    ModelState.AddModelError("NewPassword", "Password must have at least " + minDigit + " digit(s).");
}
if (splCharCount < minSpChar)
{
    ErrorFlag = true;
    ModelState.AddModelError("NewPassword", "Password must have at least " + minSpChar + " special character(s).");
}

if (ErrorFlag)
    return View(model);
0
Max