2010-04-14 31 views
17

He visto la siguiente expresión regular en la web.expresión regular de PHP para la validación de contraseña segura

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

Se valida sólo si la cadena:

* contain at least (1) upper case letter 
    * contain at least (1) lower case letter 
    * contain at least (1) number or special character 
    * contain at least (8) characters in length 

Me gustaría saber cómo convertir esta expresión regular para que compruebe la cadena a

* contain at least (2) upper case letter 
* contain at least (2) lower case letter 
* contain at least (2) digits 
* contain at least (2) special character 
* contain at least (8) characters in length 

Bueno, si contiene al menos 2 dígitos superiores, inferiores, y caracteres especiales, entonces yo no lo haría necesita la longitud de 8 caracteres.

caracteres especiales incluyen:!.?

`~ @ # $%^& *() + _- = [] \ | {} ;: '",/<>

+2

favor definir * * carácter especial. ¿Quiere decir solamente: '! @ # $%^& *() -_ = + [{]} ;: '", <.> /? 'O tal vez algo más? – Crozin

+0

actualizó la pregunta con el conjunto de caracteres especiales – Jason

+4

Don ¿Odias esos sitios web que restringen la complejidad de contraseñas "por razones de seguridad"? Quieres establecer ".evmhcfcyK" (fácil de recordar porque proviene de una oración) y terminas con "abcd1234" escrito en un post-it note. –

Respuesta

31

La mejor manera de adaptar esa expresión regular es tirarla y escribir algún código en su lugar. La expresión regular requerida sería tan larga y complicada, que no podría leerla dos horas después de haberla escrito. El código PHP equivalente será tedioso, pero al menos podrá comprender lo que escribió.

Esto no es un golpe para ti, por cierto. En la mayoría de los casos, los regex son apenas adecuados para la validación de la contraseña, pero sus requisitos son más complicados de lo habitual y simplemente no lo vale. Además, esa expresión regular que publicaste es una mierda. Nunca confíes en las expresiones regulares que encuentres flotando en la web. O cualquier código, para el caso. O, diablos, cualquier cosa. : -/

+3

Acepto, es mejor ejecutar cheques por separado, no una magia regex. De esta forma, puede modificar fácilmente partes específicas o agregarlas/eliminarlas. Personalmente, no creo que forzar una contraseña segura sea una buena experiencia de usuario, esas JS basadas Las barras de "fuerza de contraseñas" son mucho mejores porque ambos están educando al usuario y castigándolo levemente por usar una contraseña incorrecta, pero si realmente quieren usar uno, pueden hacerlo. – TravisO

+0

ok ok ... todos me convencen ... yo no probará la expresión regular ya que es claramente ilegible. Gracias a todos ¡mi! – Jason

+0

@TravisO: Sí, también me gustan esas barras de contraseñas. –

16

Si realmente desea utilizar una expresión regular, intente esto:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$ 

algunas explicaciones:

  • (?=^(?:[^A-Z]*[A-Z]){2}) pruebas durante dos repeticiones de [^A-Z]*[A-Z] que es una secuencia de cero o más caracteres excepto letras mayúsculas seguidas de una letra mayúscula
  • (?=^(?:[^a-z]*[a-z]){2}) (igual que la anterior con letras minúsculas)
  • (?=^(?:\D*\d){2}) (igual al anterior con dígitos)
  • (?=^(?:\w*\W){2}) (igual al anterior con caracteres no-palabra, pero es posible cambiar \W con una clase de caracteres de cualquier carácter especial que desea)
  • ^[A-Za-z\d\W]{8,}$ pone a prueba la longitud del conjunto cadena que consiste solamente en el carácter de la unión de todas las otras clases de caracteres.
+0

Excelente respuesta con una buena explicación, estoy votando esto aunque no recomiendo su respuesta. En este caso, creo que se está volviendo ilegible, el código estándar sería una mejor opción, la única razón por la que usaría expresiones regulares porque el rendimiento extremo era un problema y necesitaba verificar millones de contraseñas. – TravisO

+1

En realidad, si el rendimiento fuera un factor, sería otra razón * no * para usar una expresión regular. De lo contrario, estoy de acuerdo: +1 para la solución definitiva de expresiones regulares (en caso de que realmente tenga que seguir esa ruta). –

+0

+1 Pero en lugar de proporcionar una expresión regular larga e ilegible en formato nativo (y una explicación separada), es mucho mejor (y menos trabajo) escribir la expresión regular en modo de espacio libre desde el principio, completando con la sangría adecuada y comentarios generosos Un beneficio adicional es que una expresión regular de auto-documentación de espacios libres es mucho más fácil de mantener en el futuro. – ridgerunner

62

Tengo que estar de acuerdo con Alan. Si la expresión regular existente es tan complicada, ¿por qué intentar hacerlo en una sola expresión regular?

Solo desglosa en pasos simples y accesibles. Ya has hecho eso.

Ahora escriba 4 regex para validar sus partes, agregue lógica básica a la 4 regex y mida la longitud de la cadena. Hecho.

¿Qué prefieres depuración, esto:

(?=^(?:[^A-Z]*[A-Z]){2})(?=^(?:[^a-z]*[a-z]){2})(?=^(?:\D*\d){2})(?=^(?:\w*\W){2})^[A-Za-z\d\W]{8,}$ (que no funciona por cierto ...)

o esto:

function valid_pass($candidate) { 
    $r1='/[A-Z]/'; //Uppercase 
    $r2='/[a-z]/'; //lowercase 
    $r3='/[[email protected]#$%^&*()\-_=+{};:,<.>]/'; // whatever you mean by 'special char' 
    $r4='/[0-9]/'; //numbers 

    if(preg_match_all($r1,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r2,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r3,$candidate, $o)<2) return FALSE; 

    if(preg_match_all($r4,$candidate, $o)<2) return FALSE; 

    if(strlen($candidate)<8) return FALSE; 

    return TRUE; 
} 

¿Por qué la gente siente que tiene que escribir una expresión regular que nadie puede entender solo para poder hacerlo de una vez, está más allá de mí ...


Ok ok - si realmente quieres una expresión regular, aprende sobre lookaheads para validar tus reglas.

Este monstruo hace lo que le pide de una sola vez:

^          # start of line 
(?=(?:.*[A-Z]){2,})      # 2 upper case letters 
(?=(?:.*[a-z]){2,})      # 2 lower case letters 
(?=(?:.*\d){2,})       # 2 digits 
(?=(?:.*[[email protected]#$%^&*()\-_=+{};:,<.>]){2,}) # 2 special characters 
(.{8,})         # length 8 or more 
$          # EOL 

Demo

+0

Me gusta esta solución; agradable y claro lo que está pasando mientras que es razonablemente conciso. +1 – andrhamm

+0

@andrhamm ¿Hay alguna manera de conectar las primeras dos líneas? ¿Los caracteres superiores o inferiores no son superiores ni inferiores? – Byakugan

+0

@Byakugan try $ r1 = '/ [A-Za-z] /'; // Mayúsculas o minúsculas – andrhamm

Cuestiones relacionadas