segura - Regex para validar la fuerza de la contraseña
validar la complejidad de las contraseñas c# (8)
Mi criterio de fortaleza de la contraseña es el siguiente:
- 8 caracteres de longitud
- 2 letras en mayúscula
- 1 carácter especial
(!@#$&*)
- 2 numerales
(0-9)
- 3 letras en minúsculas
¿Alguien puede darme expresiones regulares por lo mismo? Todas las condiciones se deben cumplir con una contraseña.
La solución de codaddict funciona bien, pero esta es un poco más eficiente: (sintaxis de 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)
Las clases de caracteres negadas consumen todo hasta el carácter deseado en un solo paso, requiriendo cero retroceso. (La solución de punto estrella funciona bien, pero requiere algo de retroceso). Por supuesto, con cadenas de destino cortas como contraseñas, esta mejora de la eficiencia será insignificante.
Las respuestas dadas anteriormente son perfectas, pero sugiero usar varias expresiones regulares más pequeñas en lugar de grandes.
La división de la expresión regular larga tiene algunas ventajas:
- facilidad para escribir y leer
- facilidad para depurar
- facilidad para agregar / eliminar parte de la expresión regular
En general, este enfoque mantiene el código fácilmente mantenible .
Habiendo dicho eso, comparto un fragmento de código que escribo en Swift como ejemplo:
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 []
}
}
}
Otra solución:
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()
Para PHP, ¡esto funciona bien!
if(preg_match("/^(?=(?:[^A-Z]*[A-Z]){2})(?=(?:[^0-9]*[0-9]){2}).{8,}$/",
''CaSu4Li8'')){
return true;
}else{
return fasle;
}
en este caso, el resultado es verdadero
Thsks para @ridgerunner
Puede hacer estos controles utilizando afirmaciones de aspecto positivo:
^(?=.*[A-Z].*[A-Z])(?=.*[!@#$&*])(?=.*[0-9].*[0-9])(?=.*[a-z].*[a-z].*[a-z]).{8}$
Explicación:
^ 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.
Puede usar look-aheads positivos de longitud cero para especificar cada una de sus restricciones por separado:
(?=.{8,})(?=.*/p{Lu}.*/p{Lu})(?=.*[!@#$&*])(?=.*[0-9])(?=.*/p{Ll}.*/p{Ll})
Si su motor regex no admite la notación /p
y ASCII puro es suficiente, puede reemplazar /p{Lu}
con [AZ]
y /p{Ll}
con [az]
.
Sugeriría agregar
(?!.*pass|.*word|.*1234|.*qwer|.*asdf) exclude common passwords
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))