web-dev-qa-db-fra.com

Expression régulière pour vérifier si le mot de passe est "8 caractères dont 1 lettre majuscule, 1 caractère spécial, caractères alphanumériques"

Je veux une expression régulière pour vérifier que 

un mot de passe doit comporter huit caractères, dont une lettre majuscule, un caractère spécial et des caractères alphanumériques.

Et voici mon expression de validation qui consiste en huit caractères, dont une lettre majuscule, une lettre minuscule et un chiffre ou un caractère spécial.

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

Comment puis-je l'écrire pour un mot de passe qui doit comporter huit caractères, dont une lettre majuscule, un caractère spécial et des caractères alphanumériques?

96
Rania Umair

L'expression régulière que vous recherchez sera probablement énorme et un cauchemar à maintenir, en particulier pour les personnes qui ne sont pas familiarisées avec les expressions régulières.

Je pense qu'il serait plus facile de décomposer votre regex et de le faire un à un. Cela prendra peut-être un peu plus, mais je suis à peu près sûr que le maintenir et le déboguer serait plus facile. Cela vous permettrait également de fournir à vos utilisateurs des messages d'erreur plus ciblés (autres que simplement Invalid Password), ce qui devrait améliorer l'expérience utilisateur.

D'après ce que je vois, vous parlez assez couramment regex. Je suppose donc que vous donner les expressions régulières pour faire ce dont vous avez besoin serait futile.

En voyant votre commentaire, voici comment je procéderais:

  • Doit être composé de huit caractères. Long: vous n'avez pas besoin d'une expression régulière pour cela. L'utilisation de la propriété .Length devrait suffire.

  • Incluant une lettre majuscule: Vous pouvez utiliser l'expression régulière [A-Z]+. Si la chaîne contient au moins une lettre majuscule, cette expression régulière donnera true.

  • Un caractère spécial: vous pouvez utiliser soit le \W qui correspond à tout caractère qui n’est pas une lettre ou un chiffre, ou vous pouvez utiliser quelque chose comme so so [!@#] pour spécifier une liste personnalisée de caractères spéciaux. Notez cependant que les caractères tels que $, ^, ( et ) sont des caractères spéciaux du langage des expressions régulières. Ils doivent donc être échappés de la manière suivante: \$. En bref, vous pouvez utiliser le \W.

  • Caractères alphanumériques: l’utilisation du \w+ doit correspondre à toute lettre, chiffre ou trait de soulignement.

Jetez un coup d’œil à this tutorial pour plus d’informations.

126
npinti
(                   # Start of group
    (?=.*\d)        #   must contain at least one digit
    (?=.*[A-Z])     #   must contain at least one uppercase character
    (?=.*\W)        #   must contain at least one special symbol
       .            #     match anything with previous condition checking
         {8,8}      #        length is exactly 8 characters
)                   # End of group

En une ligne:

((?=.*\d)(?=.*[A-Z])(?=.*\W).{8,8})

Sources:

95
mmdemirbas

Tant de réponses .... tout mauvais!

Les expressions régulières n'ayant pas d'opérateur AND, il est donc assez difficile d'écrire une expression rationnelle qui correspond à des mots de passe valides, lorsque la validité est définie par quelque chose ET quelque chose d'autre ET d'autre chose ...

Mais les expressions rationnelles do ont un opérateur OR, appliquez donc simplement le théorème de DeMorgan et écrivez une expression régulière qui correspond aux mots de passe invalid.

tout ce qui a moins de 8 caractèresOUtout ce qui n'a pas de chiffresOUtout ce qui n'a pas de majusculeOUtout ce qui n'a pas de caractères spéciaux

Alors:

^(.{0,7}|[^0-9]*|[^A-Z]*|[a-zA-Z0-9]*)$

Si quelque chose correspond à cela, alors c'est un mot de passe invalid.

24
Matt Timmermans

Par exemple, comment cela pourrait être fait avec une expression rationnelle lisible/maintenable.

Pour une expression rationnelle plus longue, vous devez toujours utiliser RegexOptions.IgnorePatternWhitespace pour autoriser les espaces et les commentaires dans l'expression pour une meilleure lisibilité.

String[] passwords = { "foobar", "Foobar", "Foobar1", "Fooobar12" };

foreach (String s in passwords) {

    Match password = Regex.Match(s, @"
                                      ^              # Match the start of the string
                                       (?=.*\p{Lu})  # Positive lookahead assertion, is true when there is an uppercase letter
                                       (?=.*\P{L})   # Positive lookahead assertion, is true when there is a non-letter
                                       \S{8,}        # At least 8 non whitespace characters
                                      $              # Match the end of the string
                                     ", RegexOptions.IgnorePatternWhitespace);

    if (password.Success) {
        Console.WriteLine(s + ": valid");
    }
    else {
        Console.WriteLine(s + ": invalid");
    }
}

Console.ReadLine();
10
stema

La réponse est de ne pas utiliser une expression régulière. C'est définit et compte.

Les expressions régulières concernent l’ordre.

Dans votre vie de programmeur, il vous sera demandé de faire beaucoup de choses qui n’ont pas de sens. Apprenez à creuser un niveau plus profond. Apprenez quand la question est fausse.

La question (si elle mentionnait des expressions régulières) est fausse.

Pseudocode (commutation entre trop de langues, récemment):

if s.length < 8:
    return False
nUpper = nLower = nAlphanum = nSpecial = 0
for c in s:
    if isUpper(c):
        nUpper++
    if isLower(c):
        nLower++
    if isAlphanumeric(c):
        nAlphanum++
    if isSpecial(c):
        nSpecial++
return (0 < nUpper) and (0 < nAlphanum) and (0 < nSpecial)

Je parie que vous avez lu et compris le code ci-dessus presque instantanément. Je parie que vous avez pris beaucoup plus de temps avec la regex, et que vous êtes moins sûr que c'est correct. L'extension de la regex est risquée. Étendu l'immédiat ci-dessus, beaucoup moins.

Notez également que la question est imprécise. Le jeu de caractères ASCII ou Unicode, ou ?? En lisant la question, je suppose qu’au moins un caractère en minuscule est supposé. Donc, je pense que la dernière règle supposée devrait être:

return (0 < nUpper) and (0 < nLower) and (0 < nAlphanum) and (0 < nSpecial)

(Changer de chapeau en mettant l'accent sur la sécurité, c'est une règle vraiment énervant/pas utile.)

Apprendre à savoir quand la question est fausse est beaucoup plus important que des réponses intelligentes. Une réponse intelligente à la mauvaise question est presque toujours fausse.

9

Si vous n'avez besoin que d'une majuscule et d'un caractère spécial, cela devrait fonctionner:

@"^(?=.{8,}$)(?=[^A-Z]*[A-Z][^A-Z]*$)\w*\W\w*$"
1
user1096188

L'expression régulière que vous recherchiez est: /^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#\$%\^&\*\[\]"\';:_\-<>\., =\+\/\\]).{8,}$/u.

Exemple et test: http://regexr.com/3fhr4

1
Lucas

Vous pouvez utiliser la classe ci-dessous pour la validation:

public class PasswordValidator{

  private Pattern pattern;
  private Matcher matcher;

  private static final String PASSWORD_PATTERN =
          "((?=.*\\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%]).{6,20})";

  public PasswordValidator(){
      pattern = Pattern.compile(PASSWORD_PATTERN);
  }

  /**
   * Validate password with regular expression
   * @param password password for validation
   * @return true valid password, false invalid password
   */
  public boolean validate(final String password){

      matcher = pattern.matcher(password);
      return matcher.matches();

  }
}

où 6 et 20 sont la longueur minimale et maximale du mot de passe.

0
amit pandya

Cette question commence à être virale et beaucoup de suggestions intéressantes sont apparues.

Oui, écrire à la main est difficile. Donc, une solution plus simple consiste à utiliser un modèle. Bien que la regex résultante puisse ne pas être optimale, elle sera plus facile à maintenir et/ou à modifier, et l'utilisateur aura un meilleur contrôle sur le résultat. Il est possible que j'ai raté quelque chose. Toute critique constructive sera donc utile.

Ces liens peuvent être intéressants: correspond à au moins 2 chiffres 2 lettres dans n’importe quel ordre dans une chaîne , Langage d’expression régulière , Capture de groupes

J'utilise ce modèle (?=(?:.*?({type})){({count})}) basé sur toutes les expressions rationnelles que j'ai vues dans SO. L'étape suivante consiste à remplacer le modèle requis (number, special character ...) et à ajouter une configuration pour la longueur.

J'ai créé une petite classe pour la composition de la regex PasswordRegexGenerator.cs Un exemple:

string result = new PasswordRegexGenerator ( )
        .UpperCase ( 3, -1 )    // ... {3,}
        .Number ( 2, 4 )        // ... {2,4}
        .SpecialCharacter ( 2 ) // ... {2}
        .Total ( 8,-1 )
        .Compose ( );

/// <summary>
/// Generator for regular expression, validating password requirements.
/// </summary>
public class PasswordRegexGenerator
{
    private string _elementTemplate = "(?=(?:.*?({type})){({count})})";

    private Dictionary<string, string> _elements = new Dictionary<string, string> {
        { "uppercase", "[A-Z]" },
        { "lowercase", "[a-z]" },
        { "number", @"\d" },
        { "special", @"\W" },
        { "alphanumeric", @"\w" }
    };

    private StringBuilder _sb = new StringBuilder ( );

    private string Construct ( string what, int min, int max )
    {
        StringBuilder sb = new StringBuilder ( _elementTemplate );
        string count = min.ToString ( );

        if ( max == -1 )
        {
            count += ",";
        }
        else if ( max > 0 )
        {
            count += "," + max.ToString();
        }

        return sb
            .Replace ( "({type})", what )
            .Replace ( "({count})", count )
            .ToString ( );
    }

    /// <summary>
    /// Change the template for the generation of the regex parts
    /// </summary>
    /// <param name="newTemplate">the new template</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexTemplate ( string newTemplate )
    {
        _elementTemplate = newTemplate;
        return this;
       }

    /// <summary>
    /// Change or update the regex for a certain type ( number, uppercase ... )
    /// </summary>
    /// <param name="name">type of the regex</param>
    /// <param name="regex">new value for the regex</param>
    /// <returns></returns>
    public PasswordRegexGenerator ChangeRegexElements ( string name, string regex )
    {
        if ( _elements.ContainsKey ( name ) )
        {
            _elements[ name ] = regex;
        }
        else
        {
            _elements.Add ( name, regex );
        }
        return this;
    }

    #region construction methods 

    /// <summary>
    /// Adding number requirement
    /// </summary>
    /// <param name="min"></param>
    /// <param name="max"></param>
    /// <returns></returns>
    public PasswordRegexGenerator Number ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "number" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator UpperCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "uppercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator LowerCase ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "lowercase" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator SpecialCharacter ( int min = 1, int max = 0 )
    {
        _sb.Append ( Construct ( _elements[ "special" ], min, max ) );
        return this;
    }

    public PasswordRegexGenerator Total ( int min, int max = 0 )
    {
        string count = min.ToString ( ) + ( ( max == 0 ) ? "" : "," + max.ToString ( ) );
        _sb.Append ( ".{" + count + "}" );
        return this;
    }

    #endregion

    public string Compose ()
    {
        return "(" + _sb.ToString ( ) + ")";
    }
}
0
Bakudan