Regexp Java per la convalida della password


109

Sto creando una regexp per la convalida della password da utilizzare in un'applicazione Java come parametro di configurazione.

La regexp è:

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

La politica della password è:

  • Almeno 8 caratteri

  • Contiene almeno una cifra

  • Contiene almeno un carattere alfa inferiore e un carattere alfa superiore

  • Contiene almeno un carattere all'interno di un insieme di caratteri speciali ( @#%$^ecc.)

  • Non contiene spazio, tabulazione, ecc.

Manca solo il punto 5. Non riesco a far controllare la regexp per spazio, tabulazione, ritorno a capo, ecc.

Qualcuno può aiutarmi?


3
Le regole della password sono cattive. Per ulteriori informazioni, vedere Riferimento - Convalida della password .
ctwheels

Risposte:


317

Prova questo:

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

Spiegazione:

^                 # 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

È facile aggiungere, modificare o rimuovere singole regole, poiché ogni regola è un "modulo" indipendente.

Il (?=.*[xyz])costrutto mangia l'intera stringa ( .*) e torna alla prima occorrenza in cui [xyz]può corrispondere. Ha successo se [xyz]viene trovato, altrimenti fallisce.

L'alternativa sarebbe utilizzare un qualificatore riluttante: (?=.*?[xyz]). Per un controllo della password, questo non farà quasi alcuna differenza, per stringhe molto più lunghe potrebbe essere la variante più efficiente.

La variante più efficiente (ma più difficile da leggere e mantenere, quindi la più soggetta a errori) sarebbe (?=[^xyz]*[xyz]), ovviamente. Per una regex di questa lunghezza e per questo scopo, sconsiglierei di farlo in questo modo, poiché non ha vantaggi reali.


15
@ Kerby82: nelle stringhe Java, i backslash devono essere sottoposti a escape. Prova a usare \\s. Questo è un requisito Java, non un requisito regex.
Tomalak,

1
@ Allov Pensaci in questo modo: tutto ciò che non viene applicato è opzionale. Basta rimuovere i controlli per le cose che non vuoi applicare. Dovrebbe essere facile adattare la soluzione alle proprie esigenze.
Tomalak

3
Questa risposta è stata aggiunta alle domande frequenti sull'espressione regolare di overflow dello stack , in "Attività comuni di convalida".
aliteralmind

1
@ shA.t È la stessa cosa. Ho solo cercato di mantenere lo (?=...)schema in modo che corrispondesse
all'impostazione

2
@ shA.t Che tu dica "contiene solo caratteri non spazi" ( (?=\S+$)) o "non contiene caratteri spazio" ( (?!.*\s)) è una questione di preferenza. Usa quello che preferisci. :)
Tomalak

55

semplice esempio usando regex

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));
   }
}

spiegazioni:

  • (?=.*[0-9]) una cifra deve comparire almeno una volta
  • (?=.*[a-z]) una lettera minuscola deve comparire almeno una volta
  • (?=.*[A-Z]) una lettera maiuscola deve comparire almeno una volta
  • (?=.*[@#$%^&+=]) un carattere speciale deve comparire almeno una volta
  • (?=\\S+$) nessuno spazio bianco consentito nell'intera stringa
  • .{8,} almeno 8 caratteri

5
. {5,10} rappresenta un minimo di 5 caratteri e un massimo di 10 caratteri. Nel caso qualcuno stia cercando una spiegazione specifica.
abhy

@iabhi, stavo cercando questo. Grazie.
Akshatha Srinivas

Sto cercando di implementare Regex su una password memorizzata in un array di caratteri invece di una stringa per motivi di sicurezza. Ma come si applicano le espressioni regolari a un array di caratteri?
AgentM

13

Tutte le risposte fornite in precedenza utilizzano la stessa tecnica (corretta) per utilizzare un lookahead separato per ogni requisito. Ma contengono un paio di inefficienze e un bug potenzialmente enorme, a seconda del back-end che utilizzerà effettivamente la password.

Inizierò con la regex dalla risposta accettata:

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

Prima di tutto, poiché Java supporta \Ae \zpreferisco utilizzarli per assicurarmi che l'intera stringa sia convalidata, indipendentemente da Pattern.MULTILINE. Ciò non influisce sulle prestazioni, ma evita errori quando le regex vengono riciclate.

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

Il controllo che la password non contenga spazi bianchi e il controllo della sua lunghezza minima può essere eseguito in un unico passaggio utilizzando tutto in una volta inserendo quantificatore variabile {8,}sulla scorciatoia \Sche limita i caratteri consentiti:

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

Se la password fornita contiene uno spazio, verranno eseguiti tutti i controlli, solo per far fallire il controllo finale sullo spazio. Questo può essere evitato sostituendo tutti i punti con \S:

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

Il punto dovrebbe essere usato solo se vuoi veramente consentire qualsiasi carattere. Altrimenti, usa una classe di caratteri (negata) per limitare la tua regex solo a quei caratteri che sono realmente consentiti. Anche se in questo caso fa poca differenza, non usare il punto quando qualcos'altro è più appropriato è un'ottima abitudine. Vedo troppi casi di backtracking catastrofico perché lo sviluppatore era troppo pigro per usare qualcosa di più appropriato del punto.

Poiché ci sono buone probabilità che i test iniziali trovino un carattere appropriato nella prima metà della password, un quantificatore pigro può essere più efficiente:

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

Ma ora per la questione davvero importante: nessuna delle risposte menziona il fatto che la domanda originale sembra essere stata scritta da qualcuno che pensa in ASCII. Ma in Java le stringhe sono Unicode. I caratteri non ASCII sono consentiti nelle password? Se lo sono, solo gli spazi ASCII non sono consentiti o dovrebbero essere esclusi tutti gli spazi Unicode.

Per impostazione predefinita, \scorrisponde solo agli spazi bianchi ASCII, quindi il suo inverso \Scorrisponde a tutti i caratteri Unicode (spazi bianchi o meno) e a tutti i caratteri ASCII diversi dagli spazi. Se i caratteri Unicode sono consentiti ma gli spazi Unicode non lo sono, UNICODE_CHARACTER_CLASSè possibile specificare il flag per \Sescludere gli spazi Unicode. Se i caratteri Unicode non sono consentiti, è [\x21-\x7E]possibile utilizzarli invece di trovare la \Scorrispondenza con tutti i caratteri ASCII che non sono uno spazio o un carattere di controllo.

Il che ci porta al prossimo potenziale problema: vogliamo consentire ai personaggi di controllo? Il primo passo per scrivere una regex corretta è specificare esattamente cosa vuoi abbinare e cosa no. L'unica risposta tecnicamente corretta al 100% è che la specifica della password nella domanda è ambigua perché non indica se determinati intervalli di caratteri come caratteri di controllo o caratteri non ASCII sono consentiti o meno.


9

Non dovresti usare Regex eccessivamente complesse (se puoi evitarle) perché lo sono

  • difficile da leggere (almeno per tutti tranne che per te stesso)
  • difficile da estendere
  • difficile eseguire il debug

Anche se potrebbe esserci un piccolo sovraccarico sulle prestazioni nell'uso di molte piccole espressioni regolari, i punti sopra lo superano facilmente.

Implementerei in questo modo:

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;
}

E dal punto di vista della sicurezza è molto meglio forzare password più lunghe, prevenire password ben note (come 12345 e pass = user) invece di rendere le password super complicate e difficili da ricordare.
Martin Rauscher

Mi piace il tuo approccio sopra. Grazie per questo!
Thomas Lang

1

Requisiti della password:

  • La password deve contenere almeno otto (8) caratteri se il sistema può supportarla.
  • Le password devono includere caratteri di almeno due (2) di questi raggruppamenti: caratteri alfabetici, numerici e speciali.

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

L'ho provato e funziona


1

Per chiunque sia interessato ai requisiti minimi per ogni tipo di personaggio, suggerirei di fare la seguente estensione sulla risposta accettata di Tomalak:

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

Si noti che questa è una stringa di formattazione e non il pattern regex finale. Sostituisci% d con il numero minimo di occorrenze richieste per: cifre, minuscole, maiuscole, non cifre / caratteri e l'intera password (rispettivamente). Il numero massimo di occorrenze è improbabile (a meno che non si desideri un massimo di 0, rifiutando efficacemente tali caratteri) ma anche quelli potrebbero essere facilmente aggiunti. Notare il raggruppamento extra attorno a ciascun tipo in modo che i vincoli min / max consentano corrispondenze non consecutive. Questo ha funzionato a meraviglia per un sistema in cui potevamo configurare centralmente quanti caratteri di ciascun tipo abbiamo richiesto e quindi fare in modo che il sito Web e due diverse piattaforme mobili recuperassero tali informazioni per costruire il modello regex basato sulla stringa di formattazione sopra.


1

Questo controlla ogni carattere speciale:

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

1

Metodo Java pronto per te, con parametri

Basta copiare e incollare e impostare i parametri desiderati.

Se non vuoi un modulo, commentalo o aggiungi un "se" come fatto da me per caratteri speciali

//______________________________________________________________________________
/**
 * 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;
}        


0

Penso che questo possa farlo anche (come modalità più semplice):

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

[Demo Regex]


0

facile

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

  1. (? = qualsiasi cosa) -> significa che il positivo guarda avanti in tutta la stringa di input e assicurarsi che questa condizione sia scritta .sample (? =. * [0-9]) -> significa assicurarsi che un numero di cifra sia scritto nella stringa all. se non scritto restituisce falso .

  2. (?! qualsiasi cosa) -> (viceversa) significa negativo guarda avanti se la condizione è scritta restituisce falso .

    close significato ^ (condizione) (condizione) (condizione) (condizione) [\ S] {8,10} $


Mentre le risposte solo codice possono fornire una soluzione al problema, alcune spiegazioni migliorerebbero notevolmente la qualità della risposta.
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>");
}

Spiegazione:

  1. Per prima cosa imposta la password come stringa e crea il set intero o.
  2. Quindi controlla ogni carattere del ciclo for.
  3. Se trova un numero nella stringa, la n aggiunge 5. Quindi passa al successivo ciclo for. Character.isDigit (s.charAt (i))
  4. Questo ciclo controlla tutti gli alfabeti inseriti nella stringa. Se trova, aggiungi un altro 5 in n. Character.isLetter (s.charAt (i))
  5. Ora controlla l'intero n con la condizione if. Se n = 10 è vero la stringa data è alfanumerica, altrimenti no.

0

Anche tu puoi fare così.

 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;
}

0

Blocco di codice di esempio per una password complessa:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. almeno 6 cifre
  2. fino a 18 cifre
  3. un numero
  4. una minuscola
  5. uno maiuscolo
  6. può contenere tutti i caratteri speciali

0

RegEx è -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. almeno 8 cifre {8,}
  2. almeno un numero (? =. * \ d)
  3. almeno una minuscola (? =. * [az])
  4. almeno una maiuscola (? =. * [AZ])
  5. almeno un carattere speciale (? =. * [@ # $% ^ & + =])
  6. Nessuno spazio [^ \ s]
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.