Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Sprawdzanie hasła preg_match()
Forum PHP.pl > Forum > PHP
xeveot
Witam

Ma ktoś może jakiś sprawdzony sposób na sprawdzenie hasła pod warunkiem że zawiera:
- małą literę
- wielką literę
- cyfrę od 0 do 9
- znak specjalny

Gdzieś czytałem że można użyć w wyrażeniu znak "?=" ale nie wiem zbytnio jak go zastosować.
Dziękuje i pozdrawiam.
230005
[a-z0-9]/i <- to i na końcu oznacza, że wyrażenie nie jest case sensitive. Znaki specjalne chyba będziesz musiał wpisać ręcznie (nie przypominam sobie żeby była jakaś klasa dla nich), po cyfrach. A w ogóle to tutaj jest odpowiedź :]
xeveot
a takie wyrażenie jest prawidłowe?


  1. <?php
  2. preg_match('/^(?=.+[a-z])(?=.+[A-Z])(?=.+[!@#$%^&*()_+|])(?=.+[0-9])[a-zA-Z0-9!@#$%^&*()_+|]{6,16}$/D', $_POST['haslo'])
  3. ?>


Działać działa ale może ktoś mi powiedzieć jak przerobić je na wyrażenie z tym znaczkiem na końcu "/i "
230005
Wow biggrin.gif Po co aż tak komplikować?questionmark.gif To powinno być poprawne:

  1. <?php
  2. preg_match('/([[:alnum:]]+[!@#$%^&*()_+|]){6,16}/i', $_POST['haslo']);
  3. ?>


[[:alnum:]] to klasa znaków alfanumerycznych. Jeśli jednak chcesz żeby hasło mogło mieć polskie znaki musisz użyć funkcji mb_ereg.
xeveot
EDIT: Sorry działa, dziękuje bardzo
Brick
Szukałem odpowiedzi na bardzo podobne pytanie i znalazłem ten post, niestety podane rozwiązanie jest błędne, ponieważ:
- zwraca true gdy na końcu ciągu jest znak specjalny, a nie dowolne jego wystąpienie.
- warunek {6,16} zwraca true jeżeli wystąp iminimum 6 razy kombinacja: dowolny znak alfanumeryczny potem znak specjalny.

Nie udało mi się niestety napisać takiego jednego wyrażenia, które by sprawdzało wszystkie podane warunki na raz.
Ja zrobiłem to za pomocą czterech oddzielnych wyrażeń:
  1. <?php
  2. $w1 = preg_match("/[A-Z]/",$string);
  3. $w2 = preg_match("/[a-z]/",$string);
  4. $w3 = preg_match("/[0-9]/",$string);
  5. $w4 = preg_match("/[!@#$%^&*()_+|-]/",$string);
  6.  
  7. $sum = $w1+$w2+$w3+$w4;
  8. if ($sum<4) print "Złe hasło";
  9. ?>

Zapewne da się to bardziej uprościć tylko pytanie czy jest sens tracić na to czas.
Conrado81
Ja również szukałem odpowiedzi na bardzo podobne pytanie i również znalazłem ten post biggrin.gif
Stworzyłem coś takiego:
  1. <?php
  2. if (!preg_match('/^[\w!@#$%\^&*\(\)_+\|]{2,16}$/', $haslo)) $zlehaslo = TRUE;
  3. ?>
Brick
Ale w ogóle sprawdziłeś to?
To zupełnie nie działa, zwraca TRUE w przypadku prostego hasła np "piwo"
To wyrażenie jest spełnione gdy na początku ciąg znaków znajdą się minimum 3 znaki składające się na słowo (włącznie ze znakami podkreślenia). Zupełnie nie o to chodzi przecież.

Da się to zrobić jednym wyrażeniem:

  1. if (preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-])/",$pass))
  2. print "Dobre hasło";
  3. else
  4. print "Złe hasło";

Nie ja to wymyśliłem (niestety) sad.gif ale rozwiązanie jest dobre, sprawdzone.
unloco
Mógłby ktoś objaśnić wyrażenie

  1. preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-])/",$pass))


? Gdyż szukam wszędzie i nigdzie nie mogę zobaczyć co oznacza np "?=" oraz ".*"

Rozumiem, że hasło może składać się z:
-dużych liter
-małych liter
-cyfr 0-9
-znaków "!@#$%^&*()_+|-"

Ale tak jak napisałem nie wiem po co jest na początku i na końcu "/" oraz ten znak zapytania ze znakiem równości i kropka z gwiazdką

Z góry dzięki.
Brick
Cytat
Rozumiem, że hasło może składać się z:...

Nie może tylko musi.

Cytat
Ale tak jak napisałem nie wiem po co jest na początku i na końcu "/"

Wyrażenia regularne ujmuje się w znaki odwrotnego ukośnika, który pełni rolę znaku ograniczającego. Czyli początek i koniec wyrażenia.

Cytat
szukam wszędzie i nigdzie nie mogę zobaczyć co oznacza np "?=" oraz ".*"

Tutaj mamy zastosowany pewien trick z "górnej półki".
Normalnie:
? - oznacza zero lub jedno wystąpienie
* - oznacza zero lub więcej wystąpień
. - oznacza dowolny jeden znak

Ale w naszym przypadku te symbole mają inne znaczenie.
(?= ) oznacza sprawdzenie dopasowania ale bez przesuwania się wzdłuż ciągu znaków. Wyrażenie jest sprawdzane ale dalsze matchowanie startuje od tego samego miejsca, jakby tego wcale nie było. Takie patrzenie w przod, bez ruszania sie z miejsca.
Tak wiec (?=.*[A-Z]) sprawdza, czy jest duza litera gdzies dalej, ale jestesmy nadal przed nia i mozemy sprawdzic czy jest tez cos innego.
Ta sztuczka pozwala na sprawdzenie wystąpień różnych znaków bez sprawdzania kolejności ich wystąpień. Czyli zarówno "A1b" jest poprawne jak i "Ba1".
everth
Jak chcesz mniej więcej złapać jak budować RegExy, to tu masz w miarę sensownie podaną dokumentację z przykładami.
MatBlo
Chciałbym odświeżyć temat, wyrażenie podane przez unloco jak najbardziej działa

Cytat(unloco @ 19.08.2010, 19:30:44 ) *
  1. preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-])/",$pass))


chciałbym je zmodyfikować tak aby hasło składało się minimum z 8 a maksimum z 30 znaków.
  1. preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-]){8,30}/",$pass))

niestety podane przeze mnie rozwiązanie nie działa i nie bardzo wiem jak sobie z tym poradzić.
kiler129
Jedna uwaga - a-z nie obejmuje polskich ogonków. Jeśli chcesz aby były dozwolone to musisz je dopisać do wyrażenia.
MatBlo
Tak wiem wystarczy zamiast A-Z wpisać A-Ż, ale nie z tym mam problem, w każdym razie dzięki za zwrócenie uwagi.

edit.
Problem rozwiązany:
  1. preg_match("/^(?=.{8,})(?=.*[A-Ż])(?=.*[a-ż])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-]).*$/",$pass))
Brick
Działa dla min. 8 znaków, ale nie ma sprawdzania czy hasło przekracza 30 znaków.
Cytat
wyrażenie podane przez unloco jak najbardziej działa

A ktoś pisał że nie działa?
Dla ścisłości: unloco tylko wkleił wyrażenie ze wcześniejszego posta
gsk
  1. function haslo($haslo, $dlugosc, $minDuze, $minMale, $minLiczby, $minZnaki) {
  2. $minMaleLicz = 0;
  3. $minDuzeLicz = 0;
  4. $minLiczbyLicz = 0;
  5. $minZnakiLicz = 0;
  6. $haslo = iconv('UTF-8', 'ISO-8859-2', $haslo);
  7. for ($i = 0; $i < strlen($haslo); $i++) {
  8. $h = ord($haslo[$i]);
  9. //malelitery i polskie duze litery
  10. if(($h>96 && $h < 123) || $h==177 || $h==230 || $h==234 || $h==179 || $h==241 || $h==243 || $h==182 || $h==188 || $h==191) $minMaleLicz++;
  11. //duzelitery i polskie duze litery
  12. elseif (($h>64 && $h < 91) || $h==161 || $h==198 || $h==202 || $h==163 || $h==209 || $h==211 || $h==166 || $h==172 || $h==175) $minDuzeLicz++;
  13. //liczby
  14. elseif($h > 47 && $h < 58) $minLiczbyLicz++;
  15. //znaki
  16. elseif(preg_match('/[!@#$%^&*()-+_{}|:";\',.\/<>?\[\]\=]/', $haslo[$i])) $minZnakiLicz++;
  17. }
  18. if (strlen($haslo) < $dlugosc || $minMaleLicz < $minMale || $minDuzeLicz < $minDuze || $minLiczbyLicz < $minLiczby || $minZnakiLicz < $minZnaki)
  19. return false;
  20. else
  21. return true;
  22. }
  23.  
  24.  
  25. echo haslo('ĄĆŹml;†sds343aa12!@', 10, 2, 2, 2, 2);


Kiedys takie cos napisalem... Prosta funkcja zwracajaca true w przypadku, gdy haslo spelnia warunki lub false jezeli nie.
Brick
Tą "prostą funkcję" można zastąpić jedną linijką wyrażenia regularnego:
  1. if (preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-]).{8,30}$/",$pass))
  2. print "Dobre haslo";
  3. else
  4. print "Złe haslo";

Podane wyrażenie zwraca TRUE jeżeli hasło ma więcej niż 8 znaków ale nie więcej niż 30 znaków oraz jeżeli zawiera:
- jedną małą literę i
- jedną dużą literę i
- jedną cyfrę i
- jeden znak specjalny
id4
Cytat(Brick @ 25.11.2010, 20:16:27 ) *
Tą "prostą funkcję" można zastąpić jedną linijką wyrażenia regularnego:
  1. if (preg_match("/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+|-]).{8,30}$/",$pass))
  2. print "Dobre haslo";
  3. else
  4. print "Złe haslo";

Podane wyrażenie zwraca TRUE jeżeli hasło ma więcej niż 8 znaków ale nie więcej niż 30 znaków oraz jeżeli zawiera:
- jedną małą literę i
- jedną dużą literę i
- jedną cyfrę i
- jeden znak specjalny


Witam

Dobre wyrażenie.
Ma ktoś może takie, które wymaga:
- małej litery
- dużej litery
- cyfry bądź znaku specjalnego
- limitu 6-20 znaków

Z góry dzięki za pomoc.
Brick
Cytat
Ma ktoś może takie, które wymaga:
- małej litery
- dużej litery
- cyfry bądź znaku specjalnego
- limitu 6-20 znaków

To znaczy hasło jest poprawne jeżeli zawiera przynajmniej jedną małą literę i przynajmniej jedną duża literę i przynajmniej jedną cyfrę lub znak specjalny?
Czyli hasło: Aaaaa1 jest poprawne?

Długość to sprawdzisz funkcją strlen(). Ja preferuję zrobić to oddzielnie żeby napisac użytkownikowi że ma za krótkie lub za długie hasło a nie pisać "niepoprawne" ale nie wiadomo o co dokładnie chodzi.
id4
Cytat(Brick @ 24.06.2014, 15:44:09 ) *
To znaczy hasło jest poprawne jeżeli zawiera przynajmniej jedną małą literę i przynajmniej jedną duża literę i przynajmniej jedną cyfrę lub znak specjalny?
Czyli hasło: Aaaaa1 jest poprawne?

Długość to sprawdzisz funkcją strlen(). Ja preferuję zrobić to oddzielnie żeby napisac użytkownikowi że ma za krótkie lub za długie hasło a nie pisać "niepoprawne" ale nie wiadomo o co dokładnie chodzi.


Jest tak jak piszesz.
Może być też Aaaaa@ i też będzie poprawnie.

EDIT:

Kod
'/^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9!@#$%^&*()_+|-]).{6,20}$/'
Brick
No i ok, sam wymyśliłeś zanim zdążyłem odpisać.

Należy jednak zwrócić uwagę na dwa istotne szczegóły:
1. Lista znaków specjalnych nie zawiera wszystkich znaków spoza podstawowego alfabetu. Czyli np ostrych nawiasów > <, średnika, przecinka, kropki
2. Dopasowanie nie uwzględnia polskich znaków
Czyli poniższe hasła będą nieprawidłowe:
- AAAAłł1
- AAaaa>
- Adam.S
szajens
A czy do filtrowania hasła nie można by używać poprostu funkcji: ctype_print a do loginu np ctype_alnum?
http://www.php.net/manual/en/ref.ctype.php
sazian
zamień [0-9!@#$%^&*()_+|-] na [\W\d]
Brick
Cytat
A czy do filtrowania hasła nie można by używać poprostu funkcji: ctype_print a do loginu np ctype_alnum?

Do bardzo podstawowej kontroli tak, ale raczej nic zaawansowanego. Ctype sprawdza czy dany ciąg składa się z określonego typu znaków, a nie czy w danym ciągu jest znak określonego typu.
Czyli powie ci "tak, cały ciąg składa się ze znaków alfa-numerycznych" ale nie powie że składa się tylko ze znaków alfabetu i nie ma w nim żadnej cyfry.
Można by budować jakieś warunki z OR i AND ale nie wiem czy coś sensownego z tego wyjdzie.

Cytat
zamień [0-9!@#$%^&*()_+|-] na [\W\d]

Można ale zależy czego się oczekuje:
\W - spowoduje że spacja będzie potraktowana jako znak specjalny, czyli hasło ze spacją będzie prawidłowe. Podobnie kropka, przecinek itd.
\d - jest skrótem od 0-9. Jak kto woli, można tak, można tak.
szajens
Cytat(Brick @ 30.06.2014, 16:26:42 ) *
Do bardzo podstawowej kontroli tak, ale raczej nic zaawansowanego. Ctype sprawdza czy dany ciąg składa się z określonego typu znaków, a nie czy w danym ciągu jest znak określonego typu.
Czyli powie ci "tak, cały ciąg składa się ze znaków alfa-numerycznych" ale nie powie że składa się tylko ze znaków alfabetu i nie ma w nim żadnej cyfry.
Można by budować jakieś warunki z OR i AND ale nie wiem czy coś sensownego z tego wyjdzie.



ctype oferuje również inne funkcje:
http://php.net/manual/pl/book.ctype.php

To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.