Regexp Java do weryfikacji hasła


109

Tworzę wyrażenie regularne do weryfikacji hasła, które ma być używane w aplikacji Java jako parametr konfiguracyjny.

Wyrażenie regularne to:

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

Polityka haseł to:

  • Co najmniej 8 znaków

  • Zawiera co najmniej jedną cyfrę

  • Zawiera co najmniej jeden dolny znak alfa i jeden górny znak alfa

  • Zawiera co najmniej jeden znak w zestawie znaków specjalnych ( @#%$^itp.)

  • Nie zawiera spacji, tabulacji itp.

Brakuje mi tylko punktu 5. Nie mogę sprawdzić wyrażenia regularnego pod kątem spacji, tabulacji, powrotu karetki itp.

Czy ktoś mógłby mi pomóc?


3
Zasady dotyczące haseł są złe. Aby uzyskać więcej informacji, zobacz Dokumentacja - Walidacja hasła .
ctwheels

Odpowiedzi:


317

Spróbuj tego:

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

Wyjaśnienie:

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

Łatwo jest dodawać, modyfikować lub usuwać poszczególne reguły, ponieważ każda reguła jest niezależnym „modułem”.

(?=.*[xyz])Konstrukt zjada cały ciąg ( .*) i cofa się do pierwszego wystąpienia, gdzie [xyz]może się równać. Uda się, jeśli [xyz]zostanie znaleziony, w przeciwnym razie zakończy się niepowodzeniem.

Alternatywą byłoby użycie niechętnego kwalifikatora: (?=.*?[xyz]) . W przypadku sprawdzania hasła nie będzie to miało większego znaczenia, w przypadku znacznie dłuższych ciągów może to być bardziej wydajny wariant.

Najbardziej wydajnym wariantem (ale najtrudniejszym do odczytania i utrzymania, a zatem najbardziej podatnym na błędy) byłby (?=[^xyz]*[xyz])oczywiście. W przypadku wyrażenia regularnego o tej długości i w tym celu odradzałbym robienie tego w ten sposób, ponieważ nie daje to żadnych rzeczywistych korzyści.


15
@ Kerby82: W ciągach Java należy zastosować ukośniki odwrotne. Spróbuj użyć \\s. To jest wymóg Javy, a nie wymóg wyrażenia regularnego.
Tomalak

1
@Allov Pomyśl o tym w ten sposób: wszystko, co nie jest egzekwowane, jest opcjonalne. Po prostu usuń kontrole rzeczy, których nie chcesz egzekwować. Powinno być łatwe do dostosowania rozwiązania do Twoich potrzeb.
Tomalak

3
Ta odpowiedź została dodana do często zadawanych pytań dotyczących wyrażeń regularnych przepełnienia stosu w sekcji „Typowe zadania sprawdzania poprawności”.
aliteralmind

1
@ shA.t To to samo. Próbowałem tylko zachować (?=...)wzorzec, aby pasował do konfiguracji reszty wyrażenia ..
Tomalak

2
@ shA.t To, czy powiesz „zawiera tylko znaki inne niż spacje” ( (?=\S+$)), czy „nie zawiera znaków spacji” ( (?!.*\s)), jest kwestią preferencji. Użyj tego, co lubisz lepiej. :)
Tomalak

55

prosty przykład z użyciem wyrażenia regularnego

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

Objaśnienia:

  • (?=.*[0-9]) cyfra musi wystąpić co najmniej raz
  • (?=.*[a-z]) mała litera musi wystąpić przynajmniej raz
  • (?=.*[A-Z]) wielka litera musi wystąpić przynajmniej raz
  • (?=.*[@#$%^&+=]) znak specjalny musi wystąpić przynajmniej raz
  • (?=\\S+$) w całym ciągu znaków nie można używać białych znaków
  • .{8,} co najmniej 8 znaków

5
. {5,10} reprezentuje minimum 5 i maksymalnie 10 znaków. Na wypadek gdyby ktoś szukał konkretnego wyjaśnienia.
abhy

@iabhi, szukałem tego. Dziękuję Ci.
Akshatha Srinivas

Próbuję zaimplementować Regex na hasło przechowywane w tablicy znaków zamiast ciągu ze względu na bezpieczeństwo. Ale jak zastosować wyrażenie regularne do tablicy znaków?
AgentM

13

Wszystkie udzielone wcześniej odpowiedzi wykorzystują tę samą (poprawną) technikę, aby użyć osobnego wyprzedzenia dla każdego wymagania. Ale zawierają kilka nieefektywności i potencjalnie ogromny błąd, w zależności od zaplecza, które faktycznie będzie używać hasła.

Zacznę od wyrażenia regularnego z zaakceptowanej odpowiedzi:

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

Przede wszystkim, ponieważ Java obsługuje \Ai \zwolę ich używać, aby upewnić się, że cały ciąg jest zweryfikowany, niezależnie od Pattern.MULTILINE. Nie wpływa to na wydajność, ale pozwala uniknąć błędów podczas odtwarzania wyrażeń regularnych.

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

Sprawdzenie, czy hasło nie zawiera białych znaków i sprawdzenie jego minimalnej długości, można wykonać w jednym przebiegu, używając funkcji all na raz, umieszczając zmienny kwantyfikator {8,}w skrócie, \Sktóry ogranicza dozwolone znaki:

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

Jeśli podane hasło zawiera spację, wszystkie sprawdzenia zostaną wykonane, tylko po to, aby ostatnie sprawdzenie miejsca zakończyło się niepowodzeniem. Można tego uniknąć, zastępując wszystkie kropki \S:

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

Kropki należy używać tylko wtedy, gdy naprawdę chcesz dopuścić dowolny znak. W przeciwnym razie użyj (zanegowanej) klasy znaków, aby ograniczyć swoje wyrażenie regularne tylko do tych znaków, które są naprawdę dozwolone. Chociaż w tym przypadku nie ma to większego znaczenia, nieużywanie kropki, gdy coś innego jest bardziej odpowiednie, jest bardzo dobrym nawykiem. Widzę zbyt wiele przypadków katastrofalnego cofania się, ponieważ programista był zbyt leniwy, aby użyć czegoś bardziej odpowiedniego niż kropka.

Ponieważ istnieje duża szansa, że ​​początkowe testy znajdą odpowiedni znak w pierwszej połowie hasła, leniwy kwantyfikator może być bardziej wydajny:

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

Ale teraz przejdźmy do naprawdę ważnej kwestii: żadna z odpowiedzi nie wspomina o tym, że pierwotne pytanie wydaje się być napisane przez kogoś, kto myśli w ASCII. Ale w Javie ciągi znaków to Unicode. Czy w hasłach dozwolone są znaki spoza zestawu ASCII? Jeśli tak, są dozwolone tylko spacje ASCII lub należy wykluczyć wszystkie białe spacje Unicode.

Domyślnie \sdopasowuje tylko białe znaki ASCII, więc jego odwrotność \Sdopasowuje wszystkie znaki Unicode (białe lub nie) i wszystkie znaki ASCII niebędące białymi znakami. Jeśli znaki Unicode są dozwolone, ale spacje Unicode nie są, UNICODE_CHARACTER_CLASSmożna określić flagę, aby \Swykluczyć białe znaki Unicode. Jeśli znaki Unicode nie są dozwolone, [\x21-\x7E]można ich użyć zamiast \Sznaku ASCII, które nie są spacjami ani znakami sterującymi.

Co prowadzi nas do następnego potencjalnego problemu: czy chcemy pozwolić postaciom sterującym? Pierwszym krokiem w tworzeniu odpowiedniego wyrażenia regularnego jest dokładne określenie, co chcesz dopasować, a czego nie. Jedyną w 100% poprawną technicznie odpowiedzią jest to, że specyfikacja hasła w pytaniu jest niejednoznaczna, ponieważ nie określa, czy niektóre zakresy znaków, takie jak znaki sterujące lub znaki spoza zestawu ASCII, są dozwolone, czy nie.


9

Nie powinieneś używać zbyt złożonych Regexów (jeśli możesz ich uniknąć), ponieważ tak jest

  • trudne do odczytania (przynajmniej dla wszystkich oprócz Ciebie)
  • trudne do przedłużenia
  • trudne do debugowania

Chociaż użycie wielu małych wyrażeń regularnych może wiązać się z niewielkim narzutem wydajności, powyższe punkty łatwo go przeważają.

Wdrożyłbym w ten sposób:

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

Z punktu widzenia bezpieczeństwa znacznie lepiej jest wymuszać dłuższe hasła, zapobiegać dobrze znanym hasłom (takim jak 12345 i pass = user), zamiast czynić hasła bardzo skomplikowanymi i trudnymi do zapamiętania.
Martin Rauscher

Podoba mi się twoje podejście powyżej. Dziękuję za to!
Thomas Lang,

1

Wymagane hasło:

  • Hasło powinno mieć co najmniej osiem (8) znaków, jeśli system może je obsługiwać.
  • Hasła muszą zawierać znaki z co najmniej dwóch (2) z tych grup: znaki alfanumeryczne i specjalne.

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

Przetestowałem to i działa


1

Wszystkim zainteresowanym minimalnymi wymaganiami dla każdego typu postaci proponuję następujące rozszerzenie w stosunku do zaakceptowanej odpowiedzi Tomalaka:

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

Zwróć uwagę, że jest to ciąg formatujący, a nie ostateczny wzorzec wyrażenia regularnego. Po prostu zastąp% d minimalną wymaganą liczbą wystąpień: cyfry, małe litery, wielkie litery, niecyfry / znaki i całe hasło (odpowiednio). Maksymalna liczba wystąpień jest mało prawdopodobna (chyba że chcesz mieć maksymalnie 0, skutecznie odrzucając takie znaki), ale można je również łatwo dodać. Zwróć uwagę na dodatkowe grupowanie wokół każdego typu, aby ograniczenia min / max zezwalały na niekolejne dopasowania. Zdziałało to cuda w systemie, w którym mogliśmy centralnie skonfigurować liczbę znaków każdego typu, których potrzebowaliśmy, a następnie mieć witrynę internetową oraz dwie różne platformy mobilne, aby pobrać te informacje w celu skonstruowania wzorca wyrażenia regularnego w oparciu o powyższy ciąg formatujący.


1

Ten sprawdza każdy znak specjalny:

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

1

Metoda Java gotowa dla Ciebie, z parametrami

Po prostu skopiuj i wklej i ustaw żądane parametry.

Jeśli nie chcesz modułu, po prostu skomentuj go lub dodaj "if", tak jak zrobiłem to przeze mnie dla specjalnego znaku

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

Myślę, że to również może to zrobić (jako prostszy tryb):

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

[Regex Demo]


0

Łatwy

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

  1. (? = cokolwiek) -> oznacza, że ​​wartość dodatnia oczekuje w przód we wszystkich wejściowych ciągach i upewnij się, że ten warunek jest zapisany. próbka (? =. * [0-9]) -> oznacza, że ​​w całym ciągu zapisana jest jedna cyfra. jeśli nie zostanie napisane, zwróć fałsz .

  2. (?! cokolwiek) -> (vice versa) oznacza negatywne oczekiwanie w przód, jeśli warunek jest zapisany, zwraca fałsz .

    bliskie znaczenie ^ (warunek) (warunek) (warunek) (warunek) [\ S] {8,10} $


Chociaż odpowiedzi tylko na podstawie kodu mogą dostarczyć rozwiązania problemu, niektóre wyjaśnienia znacznie poprawiłyby jakość odpowiedzi.
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>");
}

Wyjaśnienie:

  1. Najpierw ustaw hasło jako ciąg i utwórz zestaw liczb całkowitych o.
  2. Następnie sprawdź każdy znak przy pętli for.
  3. Jeśli znajdzie liczbę w ciągu, wtedy n dodaj 5. Następnie przejdź do następnej pętli for. Character.isDigit (s.charAt (i))
  4. Ta pętla sprawdza wszystkie alfabety umieszczone w ciągu. Jeśli znajdzie, dodaj jeszcze jedną 5 w n. Character.isLetter (s.charAt (i))
  5. Teraz sprawdź liczbę całkowitą n w ramach warunku if. Jeśli n = 10 jest prawdziwe, dany łańcuch jest alfanumeryczny, w przeciwnym razie nie.

0

Ty też możesz to zrobić.

 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

Przykładowy blok kodu dla silnego hasła:

(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[^a-zA-Z0-9])(?=\\S+$).{6,18}
  1. co najmniej 6 cyfr
  2. do 18 cyfr
  3. jeden numer
  4. jedna mała litera
  5. jedna wielka litera
  6. może zawierać wszystkie znaki specjalne

0

Wyrażenie regularne to -

^(?:(?=.*\d)(?=.*[a-z])(?=.*[A-Z])(?=.*[@#$%^&+=]).*)[^\s]{8,}$
  1. co najmniej 8 cyfr {8,}
  2. co najmniej jedna liczba (? =. * \ d)
  3. co najmniej jedna mała litera (? =. * [az])
  4. co najmniej jedna wielka litera (? =. * [AZ])
  5. co najmniej jeden znak specjalny (? =. * [@ # $% ^ & + =])
  6. Brak spacji [^ \ s]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.