Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP] Hashowanie hasła
Forum PHP.pl > Forum > Przedszkole
Kerth
Cześć,
krótka piłka. Czym kodować(hashować) hasła? SHA1, MD5 czy połączenie tego?
Pyton_000
http://pl1.php.net/manual/en/function.crypt.php
Im silniejsze tym lepsze, i nie na pewno wymienione przez Ciebie
redeemer
bcrypt (Blowfish):

Dla PHP >= 5.5.0:
password_hash
password_verify
Kerth
A jak mam zrobić, żeby mi nie kodowało 2 różnych haseł?

  1. $register->bindValue(":haslo", crypt($haslo), PDO::PARAM_STR);
  2. $register->bindValue(":haslo2", crypt($haslo2), PDO::PARAM_STR);

Pole bazie `haslo`->> $1$e0/.PG/.$lNIJVk/qR9OqR4wpBSSPG.
Pole bazie `haslo2`->> $1$s.1.FU2.$kCGONs2fi9OHh39B8QxUO0

Co zrobić, by w haslo2 było takie same hasło jak w haslo?
Michael2318
Byle nie md5 i koniecznie hasła z solą.
Ja polecam dla każdego usera tworzyć czas rejestracji w timestamp i zapisywać to userowi jako sól do hasła. W ten sposób każdy user ma inną sól.
redeemer
  1. $crypted = crypt($haslo);
  2.  
  3. $register->bindValue(":haslo", $crypted, PDO::PARAM_STR);
  4. $register->bindValue(":haslo2", $crypted, PDO::PARAM_STR);
questionmark.gif Zresztą to jest bez znaczenia, mogą być różne - w czym problem? No i po co Ci haslo i haslo2 w bazie?
Kerth
Cytat(Michael2318 @ 3.07.2014, 23:03:17 ) *
Byle nie md5 i koniecznie hasła z solą.
Ja polecam dla każdego usera tworzyć czas rejestracji w timestamp i zapisywać to userowi jako sól do hasła. W ten sposób każdy user ma inną sól.


Powiem Ci, że w zasadzie ja zapisuję datę rejestracji w datetime, przez co mam datę i godzinę rejestracji w jednym polu. Btw. to dobrze, że tak jest? A jeśli chodzi o takie połączenie daty w sól to mógłbyś podać jakiś mały przykład?

Cytat(redeemer @ 3.07.2014, 23:05:25 ) *
  1. $crypted = crypt($haslo);
  2.  
  3. $register->bindValue(":haslo", $crypted, PDO::PARAM_STR);
  4. $register->bindValue(":haslo2", $crypted, PDO::PARAM_STR);
questionmark.gif Zresztą to jest bez znaczenia, mogą być różne - w czym problem? No i po co Ci haslo i haslo2 w bazie?


W zasadzie to nie wiem po co ja jes zapisuje, przecież wystarczy tylko jedno.
redeemer
Wiele algorytmów ma wbudowaną obsługę soli, która jest zapisana w zwracanym hashu. Dlatego pomimo puszczenia tego samego stringa (hasła) poprzez takie funkcje jak password_hash, wyniki są różne.
Kerth
A jak ja mam to hasło odkodować?

  1. $crypted_login = crypt($_POST['haslo']);
  2. $login = $db->prepare("SELECT `nick`, `haslo` FROM `gracze` WHERE `nick` = BINARY :nick && `haslo` = BINARY :haslo");
  3. $login->bindValue(":nick", $_POST['nick'], PDO::PARAM_STR);
  4. $login->bindValue(":haslo", $crypted_login, PDO::PARAM_STR);
  5. $login->execute();
  6.  
  7. $idlogin = $db->prepare("SELECT `id` FROM `gracze` WHERE `nick` = BINARY :nick && `haslo` = BINARY :haslo");
  8. $idlogin->bindValue(":nick", $_POST['nick'], PDO::PARAM_STR);
  9. $idlogin->bindValue(":haslo", $crypted_login, PDO::PARAM_STR);
  10. $idlogin->execute();


questionmark.gif
Michael2318
hashu sie nie odkodowuje tylko koduje hasło, ktore podaje user i sprawdza czy hashe sie zgadzają.
Kerth
  1. if ($login->rowCount() == 1)
  2. {
  3. ...
  4. }
  5. if ($idlogin->rowCount() == 1)
  6. {
  7. ...
  8. }


Takie warunki mam do kodów powyżej. Więc jak mam sprawdzić czy jest takie samo. Nie rozumiem za bardzo tego.
Kerth
No to mam tak:

  1. $pass_crypt = crypt($_POST['haslo']);
  2. $login = $db->prepare("SELECT `nick`, `haslo` FROM `gracze` WHERE `nick` = BINARY :nick && `haslo` = BINARY :haslo");
  3. $login->bindValue(":nick", $_POST['nick'], PDO::PARAM_STR);
  4. $login->bindValue(":haslo", $pass_crypt, PDO::PARAM_STR);
  5. $login->execute();
  6.  
  7. $idlogin = $db->prepare("SELECT `id` FROM `gracze` WHERE `nick` = BINARY :nick && `haslo` = BINARY :haslo");
  8. $idlogin->bindValue(":nick", $_POST['nick'], PDO::PARAM_STR);
  9. $idlogin->bindValue(":haslo", $pass_crypt, PDO::PARAM_STR);
  10. $idlogin->execute();


i nadal nie loguje mi do konta.
redeemer
Polecam http://php.net/manual/pl/function.crypt.php
Kerth
Tyle mi zwraca:

1. Próba logowania:
  1. string(5) "Kerth" string(34) "$1$5g..oE..$xKTUYQsNnm1RFq.SNdTvp0"


2. Próba logowania:
  1. string(5) "Kerth" string(34) "$1$R73.GT/.$TcoBKLZYo3iJHm2Y0N4K61"


  1. var_dump($_POST['nick']);
  2. var_dump($pass_crypt);


nick jest w porządku tylko z hashem problemy. Ono za każdym razem wyświetla się inne(nie zgadza się z tym w bazie). Przy każdej próbie logowania inne.

Hasło w bazie:

$1$ZC3.uB/.$SQbz8cHGDUL1N9FMbujXP1
redeemer
Powtarzam: przeczytaj manuala, bo nie tak się sprawdza czy użytkownik podał prawidłowe "hasło" w przypadku crypt.
by_ikar
W manualu dla pasword_hash jest link do odpowiednika funkcji z php5.5 dla >=php5.3.7: https://github.com/ircmaxell/password_compat i w przykładach masz jak tego używać.
Pyton_000
Aby porównać hasła zakodowane metodą Crypt:
  1. $crypted_login = crypt($_POST['haslo'], $zakodowane_haslo_z_bazzy);
  2. if($crypted_login == $zakodowane_haslo_z_bazy {
  3. // OK
  4. } else {
  5. //Kiszka
  6. }
Kerth
A jak ja mam pobrać $zakodowane_haslo_z_bazzy ?
Turson
Jeżeli mówimy o logowaniu, to przecież musisz trzymać w bazie hasło, więc je pobierasz i porównujesz z wprowadzonym w formularzu.
by_ikar
Cytat(Kerth @ 4.07.2014, 10:25:23 ) *
A jak ja mam pobrać $zakodowane_haslo_z_bazzy ?


Jeżeli user podaje login lub email na jaki chce się zalogować - pobierasz dane. Jeżeli danych nie znajdzie, również zwracasz komunikat błędu.

  1. $msg = 'Nieprawidłowy login i/lub hasło.';
  2.  
  3. $password = isset($_POST['haslo']) ? $_POST['haslo'] : false;
  4. $nick = isset($_POST['nick']) ? $_POST['nick'] : false;
  5.  
  6. //check if request data exist
  7. if($nick && $passowrd)
  8. {
  9. $sql = $db->prepare('SELECT * FROM `gracze` WHERE `nick` = BINARY :nick');
  10. $sql->bindValue(':nick', $nick, PDO::PARAM_STR);
  11. $login = $sql->execute();
  12.  
  13. //check if user exist
  14. if(false !== $data = $login->fetch())
  15. {
  16. //compare hash from db with hash from request password
  17. if(crypt($password, $data['haslo']) == $data['haslo'])
  18. {
  19. //do something after login
  20. } else
  21. {
  22. echo $msg;
  23. }
  24. } else
  25. {
  26. echo $msg;
  27. }
  28. } else
  29. {
  30. echo $msg;
  31. }


Mniej więcej tak mogło by to wyglądać.
Kerth
Może większy fragment, bo chyba nie rozumiecie o co mi chodzi.

  1. <?php
  2. function form_logowanie(){
  3. echo('
  4. <div class = "pogrub">Logowanie do konta: </div>
  5. <form action="login.php" method="post">
  6. Wpisz Nick:<br/>
  7. <input type="text" name="nick" /><br/>
  8. Wpisz hasło:<br />
  9. <input type="password" name="haslo" /><br/>
  10. <input type="submit" value="Wyślij" name = "wyslij"/> <br/>
  11. </form>
  12. </div>
  13. ');
  14. }
  15. include 'zmienne.php';
  16. include ('inc/sql.php');
  17. if(isset($_SESSION['zalogowany'])) {
  18.  
  19. //część z danymi po zalogowaniu
  20. }else{
  21.  
  22. if(isset($_POST['wyslij'])) {
  23. $pass_crypt = crypt($haslo);
  24. $login = $db->prepare("SELECT `nick`, `haslo` FROM `gracze` WHERE `nick` = BINARY :nick && `haslo` = BINARY :haslo");
  25. $login->bindValue(":nick", $_POST['nick'], PDO::PARAM_STR);
  26. $login->bindValue(":haslo", $pass_crypt, PDO::PARAM_STR);
  27. $login->execute();
  28.  
  29. $idlogin = $db->prepare("SELECT `id` FROM `gracze` WHERE `nick` = BINARY :nick && `haslo` = BINARY :haslo");
  30. $idlogin->bindValue(":nick", $_POST['nick'], PDO::PARAM_STR);
  31. $idlogin->bindValue(":haslo", $pass_crypt, PDO::PARAM_STR);
  32. $idlogin->execute();
  33.  
  34. var_dump($_POST['nick']);
  35. var_dump($pass_crypt);
  36. var_dump($haslo);
  37.  
  38. //walidacja...
  39. if ($login->rowCount() == 1)
  40. {
  41.  
  42. if ($idlogin->rowCount() == 1)
  43. {
  44. $_SESSION['zalogowany'] = true;
  45. $_SESSION['nick'] = $_POST['nick'];
  46. $_SESSION['haslo'] = $_POST['haslo'];
  47.  
  48. header('refresh: 1;');
  49. } else {
  50. echo '<div class="red">Wpisałeś złe hasło. Spróbuj ponownie.</div>';
  51.  
  52. }
  53.  
  54. echo ('<div class="blue">Zostałeś zalogowany. Za chwilę zostaniesz przeniesiony do swojego panelu.</div>');
  55. } else {
  56.  
  57. echo ('<div class="red">* Użytkownik '.$_POST['nick'].' nie istnieje lub wpisałeś błędne hasło!</div>');
  58.  
  59. }
  60. } else {
  61. form_logowanie();
  62. ?>


Problem w tym, że nie wiem gdzie wstawić to sprawdzenie czy wpisane hasło jest takie samo jak zahashowane.

Byłby w stanie ktoś może poprawić mi kod? Ja sobie z tym nie daję rady.
by_ikar
No prawie gotowiec już ci dałem, musisz go tylko wstawić w odpowiednie miejsce i podmienić niektóre dane. I są to warunki sprawdzające czy przesłane dane do zalogowania są poprawne, czyli twój warunek: isset($_POST['wyslij']) mniej więcej.
Kerth
Ale jak za ten warunek:
  1. if(isset($_POST['wyslij'])) {

podam to:

  1. $pass_crypt = crypt($haslo);
  2. if (crypt($haslo, $pass_crypt) == $pass_crypt) {


pojawia mi się cały czas coś takiego:

  1. NULL string(34) "$1$965.cX/.$U44X4w5ZHaZuMZshS0DVB." string(0) ""
  2. * Musisz wypełnić wszystkie pola!
  3. * Hasło nie może być krótsze niż 4 znaki!
  4. * Nick nie może być krótszy niż 4 znaki!
  5. * Użytkownik nie istnieje lub wpisałeś błędne hasło!


z tym, że za każdym razem jak kliknę link do pliku login.php ten kod $1$965.cX/.$U44X4w5ZHaZuMZshS0DVB. się zmienia na inny.
Pyton_000
Nikt Ci nie powiedział że będzie taki sam.
Przecież dostałeć od *by_ikar całego gotowca. Czemu nic z tym nie zrobisz.
Kerth
To czemu jak w bazie mam: $1$ZC3.uB/.$SQbz8cHGDUL1N9FMbujXP1

to
  1. var_dump($pass_crypt);

nie zwraca mi tego kodu tylko jakiś inny losowy?
Pyton_000
Kodowanie metodą Crypt daje za każdym razem inny Hash.

Aby sprawdzić poprawność musisz to robić tak:
  1. $pass = 'twojeHasło';
  2. $encodedPassword = crypt($pass);
  3.  
  4. if(crypt($pass, $encodedPassword) == $encodedPassword) {
  5. echo 'OK';
  6. } else {
  7. echo 'Kiszka';
  8. }
Kerth
Przepraszam, może jestem za głupi czy coś ale w żaden sposób nie chce mi to działać.
Cały czas pojawia mi się:

  1. NULL string(34) "$1$bN0.Ik4.$M1bVE15aVpjbHzWIDLAzf0" string(0) ""
  2. * Musisz wypełnić wszystkie pola!
  3. * Hasło nie może być krótsze niż 4 znaki!
  4. * Nick nie może być krótszy niż 4 znaki!
  5. * Użytkownik nie istnieje lub wpisałeś błędne hasło!
minolone
Skąd bierzesz zmienną $haslo ?

Przecież masz ją z formularza więc czy nie powinieneś użyć $_POST(['haslo']) ?

Jeżeli nie pobierasz danych z $_POST to hasło leci puste, dlatego nie zgadzają Ci się dane.

Jeżeli dobrze się przyjrzysz na post #by_ikar to jest to dobrze widoczne.

Pozdrawiam

PS. posiadasz walidację z tego co widać i masz tam napisane że musisz wypełnić wszystkie pola, oczywiście nie wiemy jak ona dokładnie działa, rozdziel sobie walidację wtedy będziesz wiedział dokładnie co jest nie tak.
var_dump($_POST);

Nie możesz zbindować hasła tak jak ty to robisz, zrób tak jak pokazał ci #by_ikar, sprawdzasz czy w bazie istnieje użytkownik jeżeli tak to wtedy sprawdzasz hasło.
by_ikar
Masz tutaj gotowca, bo widzę nie bardzo rozumiesz jak to działa..

  1. <?php
  2.  
  3. include 'zmienne.php';
  4. include 'inc/sql.php';
  5.  
  6. if(isset($_SESSION['zalogowany']))
  7. {
  8.  
  9. //część z danymi po zalogowaniu
  10. } else
  11. {
  12. if('POST' == $_SERVER['REQUEST_METHOD'])
  13. {
  14. $msg = 'Nieprawidłowy login i/lub hasło.';
  15.  
  16. $password = isset($_POST['haslo']) ? $_POST['haslo'] : false;
  17. $nick = isset($_POST['nick']) ? $_POST['nick'] : false;
  18.  
  19. //sprawdzanie czy przsłane dane są prawidłowe
  20. if(mb_strlen($nick) > 3 && mb_strlen($password) > 3)
  21. {
  22. $login = $db->prepare('SELECT * FROM `gracze` WHERE `nick` = BINARY :nick');
  23. $login->bindValue(':nick', $nick, PDO::PARAM_STR);
  24. $login->execute();
  25.  
  26. //sprawdzanie czy użytkownik istnieje
  27. if(false !== $data = $login->fetch())
  28. {
  29. //porównanie hash hasła z bazy danych, z hash'em hasła przesłanego przez użytkownika
  30. if(crypt($password, $data['haslo']) == $data['haslo'])
  31. {
  32. //logowanie użytkownika
  33. $_SESSION['zalogowany'] = true;
  34. $_SESSION['nick'] = $nick;
  35. $_SESSION['haslo'] = $password;
  36.  
  37. //przekierowanie na aktualny adres
  38. header('Location: '.$_SERVER['REQUEST_URI']);
  39. } else
  40. {
  41. //komunikat błędu w przypadku różnicy hasła z bazy i przesłanego hasła
  42. echo '<div class="red">'.$msg.'</div>';
  43. }
  44. } else
  45. {
  46. //komunikat błedu dla niepoprawnego loginu
  47. echo '<div class="red">'.$msg.'</div>';
  48. }
  49. } else
  50. {
  51. //komunikat błedu kiedy login/hasło są pustę, lub mają mniej niż 3 znaki
  52. echo '<div class="red">'.$msg.'</div>';
  53. }
  54. } else
  55. {
  56. echo '
  57. <div class = "pogrub">Logowanie do konta: </div>
  58. <form action="login.php" method="post">
  59. Wpisz Nick:<br/>
  60. <input type="text" name="nick" /><br/>
  61. Wpisz hasło:<br />
  62. <input type="password" name="haslo" /><br/>
  63. <input type="submit" value="Wyślij" name = "wyslij"/> <br/>
  64. </form>
  65. </div>';
  66. }
  67. }


jeżeli używasz przy echo lub include nawiasów (mimo że nie powinieneś) to już używaj wszędzie, inaczej świadczy to tylko o tym że nie jesteś pewien prawidłowej składni. Zmień w swoim edytorze tabulatory na spacje - o wiele bardziej czytelny kod. Stosuj wcięcia w kodzie - o wiele bardziej czytelny kod. Jeżeli kod sprawia ci trudności, wstawiaj komentarze do każdej konstrukcji która jest dla ciebie niezrozumiała.
Kerth
Dzięki za pomoc, choć liczyłem, że uda mi się samemu to zrobić. Mimo to dzięki wielkie. Napisałeś, żebym stosował komentarze i stosuję, tylko ze względów prywatnych ich w kodzie nie udostępniam. Zawarte są w nich tzw. "rozkminy" smile.gif

Btw. czemu ta linijka:
  1. if(false !== $data = $login->fetch())


zwraca błąd:
  1. Fatal error: Call to a member function fetch() on a non-object in C:\WebServ\httpd\strona4\login.php on line 61

?
Już od jakiegoś czasu staram się nie używać właśnie fetch(), bo wywala mi błędy. Dlaczego?
viking
Zrób sobie var_dump($login). Fetch to metoda obiektu, w twoim przypadku pewnie będzie tam null. Do poczytania podstawy http://www.php.net/manual/pl/language.oop5.basic.php
Pyton_000
  1. if(false !== $data = $login->fetch())

na
  1. if($login !== null && (false !== $data = $login->fetch()))
by_ikar
Cytat(Kerth @ 5.07.2014, 15:05:05 ) *
Dzięki za pomoc, choć liczyłem, że uda mi się samemu to zrobić. Mimo to dzięki wielkie. Napisałeś, żebym stosował komentarze i stosuję, tylko ze względów prywatnych ich w kodzie nie udostępniam. Zawarte są w nich tzw. "rozkminy" smile.gif

Btw. czemu ta linijka:
  1. if(false !== $data = $login->fetch())


zwraca błąd:
  1. Fatal error: Call to a member function fetch() on a non-object in C:\WebServ\httpd\strona4\login.php on line 61

?
Już od jakiegoś czasu staram się nie używać właśnie fetch(), bo wywala mi błędy. Dlaczego?


No to nawet swoje prywatne komentarze wstawiaj, chyba że jest jakiś w tym problem. Pamiętaj, kod czytelniejszy dla ciebie, to i kod czytelniejszy dla nas (nie koniecznie, ale zawsze można spróbować). Co do problemu, cóż zapomniałem przez te wszystkie nakładki i orm'y że tak się nie binduje. Poprawiłem swojego posta.
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.