web-dev-qa-db-fra.com

Regex pour valider la force du mot de passe

Les critères de résistance de mon mot de passe sont les suivants: 

  • Longueur de 8 caractères
  • 2 lettres en majuscule
  • 1 caractère spécial (!@#$&*)
  • 2 chiffres (0-9)
  • 3 lettres en minuscule

Quelqu'un peut-il me donner une regex pour la même chose? Toutes les conditions doivent être remplies par mot de passe.

121
Ajay Kelkar

Vous pouvez faire ces vérifications en utilisant des assertions de regard positif:

^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$

Lien Rubulaire

Explication:

^                         Start anchor
(?=.*[A-Z].*[A-Z])        Ensure string has two uppercase letters.
(?=.*[!@#$&*])            Ensure string has one special case letter.
(?=.*[0-9].*[0-9])        Ensure string has two digits.
(?=.*[a-z].*[a-z].*[a-z]) Ensure string has three lowercase letters.
.{8}                      Ensure string is of length 8.
$                         End anchor.
373
codaddict

Vous pouvez utiliser des anticipations positives de longueur nulle pour spécifier chacune de vos contraintes séparément:

(?=.{8,})(?=.*\p{Lu}.*\p{Lu})(?=.*[!@#$&*])(?=.*[0-9])(?=.*\p{Ll}.*\p{Ll})

Si votre moteur regex ne prend pas en charge la notation \p et que pur ASCII suffit, vous pouvez remplacer \p{Lu} par [A-Z] et \p{Ll} par [a-z].

10
Joachim Sauer

Les réponses données ci-dessus sont parfaites, mais je suggère d'utiliser plusieurs expressions rationnelles plus petites plutôt qu'une grosse.
Diviser la longue expression rationnelle présente certains avantages: 

  • facilité d'écriture et de lecture 
  • facilité de débogage
  • facilité pour ajouter/supprimer une partie de regex

Généralement, cette approche garde le code facilement maintenable .

Cela dit, je partage un morceau de code que j’écris dans Swift par exemple:

struct RegExp {

    /**
     Check password complexity

     - parameter password:         password to test
     - parameter length:           password min length
     - parameter patternsToEscape: patterns that password must not contains
     - parameter caseSensitivty:   specify if password must conforms case sensitivity or not
     - parameter numericDigits:    specify if password must conforms contains numeric digits or not

     - returns: boolean that describes if password is valid or not
     */
    static func checkPasswordComplexity(password password: String, length: Int, patternsToEscape: [String], caseSensitivty: Bool, numericDigits: Bool) -> Bool {
        if (password.length < length) {
            return false
        }
        if caseSensitivty {
            let hasUpperCase = RegExp.matchesForRegexInText("[A-Z]", text: password).count > 0
            if !hasUpperCase {
                return false
            }
            let hasLowerCase = RegExp.matchesForRegexInText("[a-z]", text: password).count > 0
            if !hasLowerCase {
                return false
            }
        }
        if numericDigits {
            let hasNumbers = RegExp.matchesForRegexInText("\\d", text: password).count > 0
            if !hasNumbers {
                return false
            }
        }
        if patternsToEscape.count > 0 {
            let passwordLowerCase = password.lowercaseString
            for pattern in patternsToEscape {
                let hasMatchesWithPattern = RegExp.matchesForRegexInText(pattern, text: passwordLowerCase).count > 0
                if hasMatchesWithPattern {
                    return false
                }
            }
        }
        return true
    }

    static func matchesForRegexInText(regex: String, text: String) -> [String] {
        do {
            let regex = try NSRegularExpression(pattern: regex, options: [])
            let nsString = text as NSString
            let results = regex.matchesInString(text,
                options: [], range: NSMakeRange(0, nsString.length))
            return results.map { nsString.substringWithRange($0.range)}
        } catch let error as NSError {
            print("invalid regex: \(error.localizedDescription)")
            return []
        }
    }
}
6
Luca Davanzo

Je suggère d'ajouter

(?!.*pass|.*Word|.*1234|.*qwer|.*asdf) exclude common passwords
2
Stuart

la solution de codaddict fonctionne bien, mais celle-ci est un peu plus efficace: (syntaxe Python)

password = re.compile(r"""(?#!py password Rev:20160831_2100)
    # Validate password: 2 upper, 1 special, 2 digit, 1 lower, 8 chars.
    ^                        # Anchor to start of string.
    (?=(?:[^A-Z]*[A-Z]){2})  # At least two uppercase.
    (?=[^!@#$&*]*[!@#$&*])   # At least one "special".
    (?=(?:[^0-9]*[0-9]){2})  # At least two digit.
    .{8,}                    # Password length is 8 or more.
    $                        # Anchor to end of string.
    """, re.VERBOSE)

Les classes de caractères annulées consomment tout en un seul geste, jusqu'au caractère souhaité, ce qui nécessite un retour arrière nul. (La solution point étoile fonctionne très bien, mais nécessite un retour en arrière.) Bien sûr, avec des chaînes cibles courtes telles que des mots de passe, cette amélioration d'efficacité sera négligeable.

1
ridgerunner

Une autre solution:

import re

passwordRegex = re.compile(r'''(
    ^(?=.*[A-Z].*[A-Z])                # at least two capital letters
    (?=.*[!@#$&*])                     # at least one of these special c-er
    (?=.*[0-9].*[0-9])                 # at least two numeric digits
    (?=.*[a-z].*[a-z].*[a-z])          # at least three lower case letters
    .{8,}                              # at least 8 total digits
    $
    )''', re.VERBOSE)

def userInputPasswordCheck():
    print('Enter a potential password:')
    while True:
        m = input()
        mo = passwordRegex.search(m) 
        if (not mo):
           print('''
Your password should have at least one special charachter,
two digits, two uppercase and three lowercase charachter. Length: 8+ ch-ers.

Enter another password:''')          
        else:
           print('Password is strong')
           return
userInputPasswordCheck()
0
S.Sergey

Pour PHP, cela fonctionne bien!

 if(preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/", 
 'CaSu4Li8')){
    return true;
 }else{
    return fasle;
 }

dans ce cas le résultat est vrai

Thsks pour @ridgerunner

0
Alejandro Peña
import re

RegexLength=re.compile(r'^\S{8,}$')
RegexDigit=re.compile(r'\d')
RegexLower=re.compile(r'[a-z]')
RegexUpper=re.compile(r'[A-Z]')


def IsStrongPW(password):
    if RegexLength.search(password) == None or RegexDigit.search(password) == None or RegexUpper.search(password) == None or RegexLower.search(password) == None:
        return False
    else:
        return True

while True:
    userpw=input("please input your passord to check: \n")
    if userpw == "exit":
        break
    else:
        print(IsStrongPW(userpw))
0
ivy qin

Le mot de passe doit respecter au moins 3 des 4 règles de complexité suivantes,

[au moins 1 caractère majuscule (AZ) au moins un caractère minuscule (az) au moins un chiffre (0-9) au moins un caractère spécial - n'oubliez pas de traiter l'espace comme un caractère spécial aussi]

au moins 10 caractères 

au plus 128 caractères 

pas plus de 2 caractères identiques dans une ligne (par exemple, 111 non autorisé) 

'^ (?! . (.)\1 {2}) ((? =. [az]) (? =. [AZ]) (? =. [0- 9]) | (? =. [az]) (? =. [AZ]) (? =. [^ a-zA-Z0-9]) | (? =. [AZ ]) (? =. [0-9]) (? =. [^ a-zA-Z0-9]) | (? =. [az]) (? =. [0 -9]) (? =. * [^ A-zA-Z0-9])). {10,127} $ '

(?!. * (.)\1 {2})

(? =. [a-z]) (? =. [A-Z]) (? =. * [0-9])

(? =. [a-z]) (? =. [A-Z]) (? =. * [^ a-zA-Zo])

(? =. [AZ]) (? =. [0-9]) (? =. * [^ A-zA-Z0-9])

(? =. [a-z]) (? =. [0-9]) (? =. * [^ a-zA-Zo])

{10.127}

0
Ra Vi