Funkcja password_hash

W rzeczywistości funkcja md5 i solenie hasła za jej pomocą są uważane za przestarzałe. Uczyliśmy się jej, abyście zrozumieli dalszy materiał, a także dlatego, że możecie się z tym zetknąć, pracując z cudzymi projektami.

Istnieje bardziej zaawansowany sposób uzyskania posolonego hasła. Służy do tego funkcja password_hash. Jako pierwszy parametr przyjmuje ciąg znaków, a jako drugi - algorytm szyfrowania (o nim później) i zwraca hash tego ciągu wraz z solą.

Spróbuj uruchomić ten kod kilka razy:

html<?php
  echo password_hash('12345', PASSWORD_DEFAULT);
?>

Za każdym razem otrzymasz inny wynik, i w tym wyniku pierwsza część ciągu będzie stanowić sól, a druga część - posolonym hasłem.

Załóżmy, że mamy hash uzyskany z funkcji password_hash i jakieś hasło. Aby sprawdzić, czy to jest hash tego hasła, czy nie, należy użyć funkcji password_verify - jako pierwszy parametr przyjmuje hasło, a jako drugi - hash, i zwraca true lub false.

Spójrzmy na przykład:

html<?php
  $password = '12345'; // hasło
  $hash = '$2y$10$xoYFX1mFPxBSyxaRe3iIRutxkIWhxGShzEhjYUVd3qpCUKfJE1k7a'; // hash
  
  if (password_verify($password, $hash)) {
    // hash od tego hasła
  } else {
    // hash nie od tego hasła
  }
?>

Co nam to daje w praktyce: możemy nie tworzyć w bazie danych oddzielnego pola do przechowywania soli, nie zawracać sobie głowy generowaniem tej soli - PHP zrobi wszystko za nas!

Czyli okaże się, że w bazie danych w polu password będziemy przechowywać posolone hasło razem z jego solą. Przy tym zahashowane hasło będzie miało większą długość. Dlatego w bazie danych musimy poprawić rozmiar pola z hasłem i ustawić go na 60 znaków.

Teraz poprawmy kod rejestracji. Oto to, co jest teraz:

html<?php
  function generateSalt()
  {
    $salt = '';
    $saltLength = 8; // długość soli
    
    for($i = 0; $i < $saltLength; $i++) {
      $salt .= chr(mt_rand(33, 126)); // znak z ASCII-table
    }
    
    return $salt;
  }
  
  $salt = generateSalt(); //  sól
  $password = md5($salt . $_POST['password']); // przekształcamy hasło w posolony hash
?>

Za pomocą password_hash skrócimy to do:

html<?php
  $password = password_hash($_POST['password'], PASSWORD_DEFAULT);
?>

W analogiczny sposób poprawi się kod logowania:

html<?php
  $login = $_POST['login'];
  
  $query = "SELECT * FROM users WHERE login='$login'"; // pobieramy użytkownika po loginie
  $res = mysqli_query($link, $query);
  $user = mysqli_fetch_assoc($res);
  
  if (!empty($user)) {
    $hash = $user['password']; // posolone hasło z BD
    
    // Sprawdzamy zgodność hasha z bazy z wprowadzonym hasłem
    if (password_verify($_POST['password'], $hash)) {
      // wszystko ok, logujemy...
    } else {
      // hasło nie pasuje, wyświetlimy komunikat
    }
  } else {
    // nie ma użytkownika z takim loginem, wyświetlimy komunikat
  }
?>
Задание 1

Przerób swoją autoryzację i rejestrację na nowo poznane funkcje.