Regexp Java para validación de contraseña

109

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

La expresión regular es:

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

La política de contraseñas es:

  • Al menos 8 caracteres

  • Contiene al menos un dígito

  • Contiene al menos un carácter alfa inferior y un carácter alfa superior

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

  • No contiene espacio, tabulación, etc.

Me falta solo el punto 5. No puedo hacer que la expresión regular verifique el espacio, la pestaña, el retorno de carro, etc.

¿Alguien podría ayudarme?

Kerby82
fuente
3
Las reglas de contraseña son malas. Consulte Referencia: Validación de contraseña para obtener más información.
ctwheels

Respuestas:

317

Prueba esto:

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

Explicación:

^                 # start-of-string
(?=.*[0-9])       # a digit must occur at least once
(?=.*[a-z])       # a lower case letter must occur at least once
(?=.*[A-Z])       # 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 (?=.*[xyz])construcción se come toda la cadena ( .*) y retrocede hasta la primera aparición donde [xyz]puede coincidir. Tiene éxito si [xyz]se encuentra, de lo contrario falla.

La alternativa sería el uso de un calificativo renuente: (?=.*?[xyz]). Para una verificación de contraseña, esto apenas 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, no recomendaría hacerlo de esa manera, ya que no tiene beneficios reales.

Tomalak
fuente
15
@ Kerby82: en las cadenas de Java, las barras invertidas se deben escapar. Intente usar \\s. Ese es un requisito de Java, no un requisito de expresiones regulares.
Tomalak
1
@Allov Solo piénsalo de esa manera: todo lo que no se hace cumplir es opcional. Simplemente elimine los controles de las cosas que no desea hacer cumplir. Debería ser fácil adaptar la solución a sus necesidades.
Tomalak
3
Esta respuesta se ha agregado a las Preguntas frecuentes sobre expresiones regulares de desbordamiento de pila , en "Tareas de validación comunes".
aliteralmind
1
@ shA.t Es lo mismo. Solo traté de mantener el (?=...)patrón para que coincida con la configuración del resto de la expresión ..
Tomalak
2
@ shA.t Si dice "contiene sólo caracteres sin espacio" ( (?=\S+$)) o "no contiene caracteres de espacio" ( (?!.*\s)) es una cuestión de preferencia. Usa lo que más te guste. :)
Tomalak
55

ejemplo simple usando expresiones regulares

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

Explicaciones:

  • (?=.*[0-9]) un dígito debe aparecer al menos una vez
  • (?=.*[a-z]) una letra minúscula debe aparecer al menos una vez
  • (?=.*[A-Z]) una letra mayúscula debe aparecer al menos una vez
  • (?=.*[@#$%^&+=]) un carácter especial debe aparecer al menos una vez
  • (?=\\S+$) no se permiten espacios en blanco en toda la cadena
  • .{8,} Al menos 8 carácteres
ágiles
fuente
5
. {5,10} representa un mínimo de 5 caracteres y un máximo de 10 caracteres. Por si acaso alguien está buscando una explicación específica.
abhy
@iabhi, estaba buscando esto. Gracias.
Akshatha Srinivas
Estoy tratando de implementar Regex en una contraseña almacenada en una matriz de caracteres en lugar de una Cadena debido a la seguridad. Pero, ¿cómo se aplica una expresión regular a una matriz de caracteres?
AgentM
13

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

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

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

En primer lugar, dado que Java es compatible \Ay \zprefiero usarlos para asegurarme de que toda la cadena esté validada, independientemente de Pattern.MULTILINE. Esto no afecta el rendimiento, pero evita errores cuando se reciclan las expresiones regulares.

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

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

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

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

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

El punto solo debe usarse si realmente desea permitir cualquier carácter. De lo contrario, use una clase de caracteres (negada) para limitar su expresión regular a solo aquellos caracteres que realmente están permitidos. Aunque hay poca diferencia en este caso, no usar el punto cuando otra cosa es más apropiada es un muy buen hábito. Veo demasiados casos de retroceso catastrófico porque el desarrollador fue demasiado vago para usar algo más apropiado que el punto.

Dado que hay una buena probabilidad de que las pruebas iniciales encuentren un carácter apropiado en la primera mitad de la contraseña, un cuantificador diferido puede ser más eficiente:

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

Pero ahora 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 que no son ASCII en las contraseñas? Si es así, solo se deshabilitan los espacios ASCII o se deben excluir todos los espacios en blanco Unicode.

De forma predeterminada \s, solo coincide con los espacios en blanco ASCII, por lo que su inverso \Scoincide con todos los caracteres Unicode (espacios en blanco o no) y todos los caracteres ASCII que no son espacios en blanco. Si se permiten caracteres Unicode pero no los espacios Unicode, UNICODE_CHARACTER_CLASSse puede especificar la marca para \Sexcluir los espacios en blanco Unicode. Si no se permiten caracteres Unicode, entonces [\x21-\x7E]se pueden usar en lugar de \Spara hacer coincidir todos los caracteres ASCII que no sean un espacio o un carácter de control.

Lo que nos lleva al siguiente problema potencial: ¿queremos permitir personajes de control? El primer paso para escribir una expresión regular adecuada es especificar exactamente lo que desea hacer coincidir 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 caracteres de control o caracteres no ASCII están permitidos o no.

Jan Goyvaerts
fuente
9

No debe usar expresiones regulares demasiado complejas (si puede evitarlas) 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 al usar muchas expresiones regulares pequeñas, los puntos anteriores lo superan fácilmente.

Lo implementaría así:

bool matchesPolicy(pwd) {
    if (pwd.length < 8) return false;
    if (not pwd =~ /[0-9]/) return false;
    if (not pwd =~ /[a-z]/) return false;
    if (not pwd =~ /[A-Z]/) return false;
    if (not pwd =~ /[%@$^]/) return false;
    if (pwd =~ /\s/) return false;
    return true;
}
Martin Rauscher
fuente
Y desde una perspectiva de seguridad, es mucho mejor forzar contraseñas más largas, evitar contraseñas conocidas (como 12345 y pass = user) en lugar de hacer que las contraseñas sean muy complicadas y difíciles de recordar.
Martin Rauscher
Me gusta tu enfoque anterior. ¡Gracias por eso!
Thomas Lang
1

Requisito de contraseña:

  • La contraseña debe tener al menos ocho (8) caracteres de longitud donde el sistema pueda admitirla.
  • Las contraseñas deben incluir caracteres de al menos dos (2) de estas agrupaciones: caracteres alfabéticos, numéricos y especiales.

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

Lo probé y funciona

Andrés
fuente
1

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,})(?=(.*[a-z]){%d,})(?=(.*[A-Z]){%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 ocurrencias máximas son poco probables (a menos que desee un máximo de 0, rechazando efectivamente cualquiera de esos caracteres), pero también se podrían agregar fácilmente. Observe la agrupación adicional alrededor de cada tipo para que las restricciones mínimas / máximas permitan coincidencias no consecutivas. Esto funcionó de maravilla para un sistema en el que podíamos configurar de forma centralizada cuántos de cada tipo de carácter requerimos y luego hacer que el sitio web, así como dos plataformas móviles diferentes, obtengan esa información para construir el patrón de expresiones regulares basado en la cadena de formato anterior.

Demetrios Christopher
fuente
1

Este busca cada carácter especial:

^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=\S+$).*[A-Za-z0-9].{8,}$
Ansu
fuente
1

Método Java listo para ti, con parámetros

Simplemente copie y pegue y configure los parámetros deseados.

Si no desea un módulo, simplemente coméntelo o agregue un "si" como lo hice yo para un carácter especial

//______________________________________________________________________________
/**
 * Validation Password     */
//______________________________________________________________________________
private static boolean validation_Password(final String PASSWORD_Arg)    {
    boolean result = false;
    try {
        if (PASSWORD_Arg!=null) {
            //_________________________
            //Parameteres
            final String MIN_LENGHT="8";
            final String MAX_LENGHT="20";
            final boolean SPECIAL_CHAR_NEEDED=true;

            //_________________________
            //Modules
            final String ONE_DIGIT = "(?=.*[0-9])";  //(?=.*[0-9]) a digit must occur at least once
            final String LOWER_CASE = "(?=.*[a-z])";  //(?=.*[a-z]) a lower case letter must occur at least once
            final String UPPER_CASE = "(?=.*[A-Z])";  //(?=.*[A-Z]) an upper case letter must occur at least once
            final String NO_SPACE = "(?=\\S+$)";  //(?=\\S+$) no whitespace allowed in the entire string
            //final String MIN_CHAR = ".{" + MIN_LENGHT + ",}";  //.{8,} at least 8 characters
            final String MIN_MAX_CHAR = ".{" + MIN_LENGHT + "," + MAX_LENGHT + "}";  //.{5,10} represents minimum of 5 characters and maximum of 10 characters

            final String SPECIAL_CHAR;
            if (SPECIAL_CHAR_NEEDED==true) SPECIAL_CHAR= "(?=.*[@#$%^&+=])"; //(?=.*[@#$%^&+=]) a special character must occur at least once
            else SPECIAL_CHAR="";
            //_________________________
            //Pattern
            //String pattern = "(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}";
            final String PATTERN = ONE_DIGIT + LOWER_CASE + UPPER_CASE + SPECIAL_CHAR + NO_SPACE + MIN_MAX_CHAR;
            //_________________________
            result = PASSWORD_Arg.matches(PATTERN);
            //_________________________
        }    

    } catch (Exception ex) {
        result=false;
    }

    return result;
}        
Fausto70
fuente
1

Utilice la biblioteca Passay , que es una potente API.

Balasubramanian Rengasamy
fuente
0

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

^(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])[^\s]{8,}$

[Demostración de regex]

shA.t
fuente
0

fácil

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

  1. (? = cualquier cosa) -> significa una anticipación positiva en toda la cadena de entrada y asegúrese de que esta condición esté escrita .sample (? =. * [0-9]) -> significa asegurarse de que se escriba un número de dígito en toda la cadena. si no está escrito, devuelva falso .

  2. (?! cualquier cosa) -> (viceversa) significa una mirada negativa hacia adelante si se escribe la condición return false .

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

ibrahem shabban
fuente
Si bien las respuestas de solo código pueden proporcionar una solución al problema, alguna explicación mejoraría enormemente la calidad de la respuesta.
Nigel Ren
0
String s=pwd;
int n=0;
for(int i=0;i<s.length();i++)
{
    if((Character.isDigit(s.charAt(i))))
    {
        n=5;
        break;
    }
    else
    {

    }
}
for(int i=0;i<s.length();i++)
{
    if((Character.isLetter(s.charAt(i))))
    {
        n+=5;
        break;
    }
    else
    {

    }

}

if(n==10)
{
    out.print("Password format correct <b>Accepted</b><br>");

}
else
{
    out.print("Password must be alphanumeric <b>Declined</b><br>");
}

Explicación:

  1. Primero establezca la contraseña como una cadena y cree un conjunto entero o.
  2. Luego, verifique el bucle de todos y cada uno de los caracteres.
  3. Si encuentra un número en la cadena, entonces la n suma 5. Luego salta al siguiente ciclo for. Character.isDigit (s.charAt (i))
  4. Este bucle verifica los alfabetos colocados en la cadena. Si se encuentra, agregue un 5 más en n. Character.isLetter (s.charAt (i))
  5. Ahora verifique el número entero n mediante la condición if. Si n = 10 es verdadero, la cadena dada es alfanumérica, de lo contrario no lo es.
Naresh Babu
fuente
0

También puedes hacer esto.

 public boolean isPasswordValid(String password) {


    String regExpn =
            "^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=])(?=\\S+$).{8,}$";

    CharSequence inputStr = password;

    Pattern pattern = Pattern.compile(regExpn,Pattern.CASE_INSENSITIVE);
    Matcher matcher = pattern.matcher(inputStr);

    if(matcher.matches())
        return true;
    else
        return false;
}
RANAJEET BARIK
fuente
0

Bloque de código de muestra para contraseña segura:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. al menos 6 dígitos
  2. hasta 18 dígitos
  3. un número
  4. una minúscula
  5. un caso superior
  6. puede contener todos los caracteres especiales
Sedrettin Çalışkan
fuente
0

La expresión regular es -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. al menos 8 dígitos {8,}
  2. al menos un número (? =. * \ d)
  3. al menos una minúscula (? =. * [az])
  4. al menos una mayúscula (? =. * [AZ])
  5. al menos un carácter especial (? =. * [@ # $% ^ & + =])
  6. Sin espacio [^ \ s]
Ankit Kumar Rajpoot
fuente