Regexp Java para la validación de contraseñas

Estoy creando una expresión regular para la validación de contraseña para usarla en una aplicación Java como parámetro de configuración.

La expresión regular es:

^.*(?=.{8,})(?=..*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=]).*$ 

La política de contraseñas es:

  • Al menos 8 caracteres

  • Contiene al menos un dígito

  • Contiene al menos un char alfa inferior y un char alfa superior

  • Contiene al menos un carácter dentro de un conjunto de caracteres especiales ( @#%$^ etc.)

  • No contiene espacio, pestaña, etc.

Me falta solo el punto 5. No puedo tener el cheque de expresión regular para el espacio, la pestaña, el retorno de carro, etc.

¿Alguien podría ayudarme?

Prueba esto:

 ^(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\S+$).{8,}$ 

Explicación:

 ^ # start-of-string (?=.*[0-9]) # a digit must occur at least once (?=.*[az]) # a lower case letter must occur at least once (?=.*[AZ]) # an upper case letter must occur at least once (?=.*[@#$%^&+=]) # a special character must occur at least once (?=\S+$) # no whitespace allowed in the entire string .{8,} # anything, at least eight places though $ # end-of-string 

Es fácil agregar, modificar o eliminar reglas individuales, ya que cada regla es un “módulo” independiente.

La construcción (?=.*[xyz]) come toda la cadena ( .* ) Y retrocede a la primera ocurrencia donde [xyz] puede coincidir. Tiene éxito si se encuentra [xyz] , de lo contrario falla.

La alternativa sería usar un calificador reacio: (?=.*?[xyz]) . Para una verificación de contraseña, esto no hará ninguna diferencia, para cadenas mucho más largas podría ser la variante más eficiente.

La variante más eficiente (pero la más difícil de leer y mantener, por lo tanto, la más propensa a errores) sería (?=[^xyz]*[xyz]) , por supuesto. Para una expresión regular de esta longitud y para este propósito, recomendaría hacerlo de esa manera, ya que no tiene ningún beneficio real.

ejemplo simple usando regex

 public class passwordvalidation { public static void main(String[] args) { String passwd = "aaZZa44@"; String pattern = "(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\\S+$).{8,}"; System.out.println(passwd.matches(pattern)); } } 

Explicaciones

  • (?=.*[0-9]) un dígito debe ocurrir al menos una vez
  • (?=.*[az]) debe aparecer una letra minúscula al menos una vez
  • (?=.*[AZ]) una letra mayúscula debe aparecer al menos una vez
  • (?=.*[@#$%^&+=]) debe aparecer un carácter especial al menos una vez
  • (?=\\S+$) no se permiten espacios en blanco en toda la cadena
  • .{8,} al menos 8 caracteres

Todas las respuestas dadas anteriormente usan la misma técnica (correcta) para usar una búsqueda anticipada separada para cada requerimiento. Pero contienen un par de ineficiencias y un error potencialmente masivo, dependiendo de la parte de atrás que usará la contraseña.

Comenzaré con la expresión regular de la respuesta aceptada:

 ^(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\S+$).{8,}$ 

En primer lugar, dado que Java admite \A y \z , prefiero usarlos para asegurarme de que toda la cadena está validada, independientemente de Pattern.MULTILINE . Esto no afecta el rendimiento, pero evita errores cuando las expresiones regulares se reciclan.

 \A(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])(?=\S+$).{8,}\z 

Verificando que la contraseña no contenga espacios en blanco y verificando su longitud mínima se puede hacer en una sola pasada usando el todo de una vez colocando el cuantificador variable {8,} en la abreviatura \S que limita los caracteres permitidos:

 \A(?=.*[0-9])(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])\S{8,}\z 

Si la contraseña provista contiene un espacio, se realizarán todas las comprobaciones, solo para que la verificación final falle en el espacio. Esto se puede evitar reemplazando todos los puntos con \S :

 \A(?=\S*[0-9])(?=\S*[az])(?=\S*[AZ])(?=\S*[@#$%^&+=])\S{8,}\z 

El punto solo debe usarse si realmente quieres permitir cualquier personaje. De lo contrario, use una clase de caracteres (negada) para limitar su expresión regular solo a aquellos caracteres que realmente están permitidos. Aunque en este caso no hace mucha diferencia, no usar el punto cuando algo más es más apropiado es un hábito muy bueno. Veo demasiados casos de retroceso catastrófico porque el desarrollador era demasiado perezoso para usar algo más apropiado que el punto.

Como es muy probable que las pruebas iniciales encuentren un carácter apropiado en la primera mitad de la contraseña, un cuantificador perezoso puede ser más eficiente:

 \A(?=\S*?[0-9])(?=\S*?[az])(?=\S*?[AZ])(?=\S*?[@#$%^&+=])\S{8,}\z 

Pero ahora, para el tema realmente importante: ninguna de las respuestas menciona el hecho de que la pregunta original parece haber sido escrita por alguien que piensa en ASCII. Pero en Java las cadenas son Unicode. ¿Se permiten caracteres no ASCII en las contraseñas? Si lo son, solo se inhabilitan los espacios ASCII o se deben excluir todos los espacios en blanco Unicode.

Por defecto \s solo coincide con el espacio en blanco ASCII, por lo que su inverso \S coincide con todos los caracteres Unicode (espacio en blanco o no) y todos los caracteres ASCII que no sean de espacio en blanco. Si se permiten caracteres Unicode pero los espacios Unicode no lo son, se puede especificar el indicador UNICODE_CHARACTER_CLASS para hacer que \S excluya el espacio en blanco Unicode. Si los caracteres Unicode no están permitidos, entonces se puede usar [\x21-\x7E] lugar de \S para hacer coincidir todos los caracteres ASCII que no sean un espacio o un carácter de control.

Lo que nos lleva al próximo problema potencial: ¿queremos permitir personajes de control? El primer paso para escribir una expresión regular adecuada es especificar exactamente lo que quiere que coincida y lo que no. La única respuesta 100% técnicamente correcta es que la especificación de la contraseña en la pregunta es ambigua porque no indica si ciertos rangos de caracteres como los caracteres de control o los caracteres no ASCII están permitidos o no.

No debe usar Regex demasiado complejo (si puede evitarlos) porque son

  • difícil de leer (al menos para todos menos para ti)
  • difícil de extender
  • difícil de depurar

Aunque puede haber una pequeña sobrecarga de rendimiento en el uso de muchas expresiones regulares pequeñas, los puntos anteriores lo superan fácilmente.

Implementaría así:

 bool matchesPolicy(pwd) { if (pwd.length < 8) return false; if (not pwd =~ /[0-9]/) return false; if (not pwd =~ /[az]/) return false; if (not pwd =~ /[AZ]/) return false; if (not pwd =~ /[%@$^]/) return false; if (pwd =~ /\s/) return false; return true; } 

Requisito de contraseña:

  • La contraseña debe tener al menos ocho (8) caracteres de longitud donde el sistema pueda soportarla.
  • Las contraseñas deben incluir caracteres de al menos dos (2) de estos grupos: caracteres alfa, numéricos y especiales.

     ^.*(?=.{8,})(?=.*\d)(?=.*[a-zA-Z])|(?=.{8,})(?=.*\d)(?=.*[!@#$%^&])|(?=.{8,})(?=.*[a-zA-Z])(?=.*[!@#$%^&]).*$ 

Lo probé y funciona

Para cualquier persona interesada en los requisitos mínimos para cada tipo de personaje, sugeriría hacer la siguiente extensión sobre la respuesta aceptada de Tomalak:

 ^(?=(.*[0-9]){%d,})(?=(.*[az]){%d,})(?=(.*[AZ]){%d,})(?=(.*[^0-9a-zA-Z]){%d,})(?=\S+$).{%d,}$ 

Tenga en cuenta que esta es una cadena de formato y no el patrón de expresión regular final. Simplemente sustituya% d con las ocurrencias mínimas requeridas para: dígitos, minúsculas, mayúsculas, no dígitos / caracteres y contraseña completa (respectivamente). Las instancias máximas son poco probables (a menos que desee un máximo de 0, rechazando efectivamente dichos caracteres) pero también podrían agregarse fácilmente. Observe la agrupación adicional alrededor de cada tipo para que las restricciones mínima / máxima permitan coincidencias no consecutivas. Esto funcionó de maravillas para un sistema en el que podíamos configurar de manera centralizada cuántos de cada tipo de personaje necesitábamos y luego hacer que el sitio web y dos plataformas móviles diferentes obtuvieran esa información para construir el patrón de expresiones regulares basado en la cadena de formato anterior.

Creo que esto también puede hacerlo (como un modo más simple):

 ^(?=.*\d)(?=.*[az])(?=.*[AZ])(?=.*[@#$%^&+=])[^\s]{8,}$ 

[Demo Regex]

fácil

(“^ (? =. * [0-9]) (? =. * [Az]) (? =. * [AZ]) (? =. * [\\ W _]) [\\ S] {8 , 10} $ “)

  1. (? = cualquier cosa) -> significa que espera en todas las cadenas de entrada y asegúrese de que esta condición esté escrita .sample (? =. * [0-9]) -> significa que se debe escribir un número de un dígito en la cadena de todos. si no está escrito devuelve falso .
  2. (?! cualquier cosa) -> (viceversa) significa negativo mira hacia adelante si la condición está escrita devuelve falso .

    significado cercano ^ (condición) (condición) (condición) (condición) [\ S] {8,10} $

 String s=pwd; int n=0; for(int i=0;iAccepted
"); } else { out.print("Password must be alphanumeric Declined
"); }

Explicación:

  1. Primero configure la contraseña como una cadena y cree el conjunto entero o.
  2. Luego, revise todos los caracteres por ciclo.
  3. Si encuentra un número en la cadena, entonces n agrega 5. Luego salta al siguiente ciclo. Character.isDigit (s.charAt (i))
  4. Este ciclo verifica cualquier alfabeto colocado en la cadena. Si es encontrar, agrega uno más 5 en n. Character.isLetter (s.charAt (i))
  5. Ahora comprueba el entero n por cierto estado. Si n = 10 es verdadero dado que la cadena es alfanumérica, de lo contrario no es así.