Хеширане на пароли
За да осигурим сигурността на нашите потребители, не съхраняваме техните пароли в четим вид, а си запазваме само отпечатък (т.нар. хеш). От отпечатъка не може обратно да се реконструира оригиналният вид на паролата. Важно е да се използва сигурен алгоритъм, с който да създадем отпечатъка. С това ни помага класът Nette\Security\Passwords.
Framework-ът автоматично добавя към DI контейнера услуга от тип
Nette\Security\Passwords
под името security.passwords
, до която можете да
стигнете, като си я поискате чрез dependency injection.
use Nette\Security\Passwords;
class Foo
{
public function __construct(
private Passwords $passwords,
) {
}
}
__construct ($algo=PASSWORD_DEFAULT, array $options=[]): string
Избираме кой сигурен алгоритъм за генериране на хеш да използваме и конфигурираме неговите параметри.
По подразбиране се използва PASSWORD_DEFAULT
, тоест изборът на
алгоритъм се оставя на PHP. Алгоритъмът може да се промени в по-нови
версии на PHP, ако се появят по-нови, по-силни хеширащи алгоритми. Затова
трябва да сте наясно, че дължината на получения хеш може да се промени и
трябва да го съхранявате по начин, който може да побере достатъчно
знаци, 255 е препоръчителната ширина.
Пример за настройка на скоростта на хеширане с алгоритъм bcrypt чрез промяна на параметъра cost: (през 2020 г. по подразбиране е 10, хеширането на парола отнема около 80ms, за cost 11 е около 160ms, за cost 12 около 320ms, колкото по-бавно, толкова по-добра защита, като скорост 10–12 вече се счита за достатъчна защита)
// ще хешираме паролите с 2^12 (2^cost) итерации на алгоритъма bcrypt
$passwords = new Passwords(PASSWORD_BCRYPT, ['cost' => 12]);
С помощта на dependency injection:
services:
security.passwords: Nette\Security\Passwords(::PASSWORD_BCRYPT, [cost: 12])
hash (string $passwords): string
Генерира хеш на паролата.
$res = $passwords->hash($password); // Хешира паролата
Резултатът $res
е низ, който освен самия хеш съдържа и
идентификатор на използвания алгоритъм, неговите настройки и
криптографска сол (случайни данни, осигуряващи, че за една и съща
парола се генерира различен хеш). Той е обратно съвместим, когато
например промените параметрите, така че и хешовете, съхранени с
използване на предишните настройки, ще могат да бъдат проверени.
Целият този резултат се съхранява в базата данни, така че не е
необходимо да се съхраняват солта или настройките отделно.
verify (string $password, string $hash): bool
Установява дали дадена парола съответства на дадения отпечатък.
$hash
вземете от базата данни според зададеното потребителско име
или имейл адрес.
if ($passwords->verify($password, $hash)) {
// правилна парола
}
needsRehash (string $hash): bool
Установява дали хешът съответства на зададените в конструктора опции.
Полезно е да се използва в момент, когато напр. променяте скоростта на
хеширане. Проверката се извършва според съхранените настройки и ако
needsRehash()
върне true
, тогава е необходимо отново да се
създаде хеш, този път с новите параметри, и да се съхрани отново в
базата данни. Така автоматично се “надграждат” съхранените хешове
при влизане на потребителите.
if ($passwords->needsRehash($hash)) {
$hash = $passwords->hash($password);
// съхрани $hash в базата данни
}