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:
<?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:
<?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:
<?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:
<?php
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
?>
W analogiczny sposób poprawi się kod logowania:
<?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
}
?>
Przerób swoją autoryzację i rejestrację na nowo poznane funkcje.