Хеширование паролей в PHP: password_hash и password_verify для безопасной авторизации
Поисковый запрос, под который написана эта статья: PHP password_hash password_verify. Если вы делаете регистрацию, личный кабинет или админку, первое правило безопасности простое: никогда не храните пароль пользователя как обычный текст. В PHP для этого есть встроенные функции password_hash() и password_verify().
Почему нельзя хранить пароль как есть
Допустим, пользователь ввёл пароль qwerty123, а вы записали его в базу данных без изменений. Если база утечёт, злоумышленник сразу получит доступ к аккаунтам. Плохо и другое решение — использовать md5 или sha1. Эти алгоритмы быстрые, устаревшие и легко перебираются по словарям.
Правильный подход — хранить не пароль, а его криптографический хеш, созданный специальным алгоритмом для паролей. В PHP это делается одной функцией:
<?php
$password = 'secret123';
$hash = password_hash($password, PASSWORD_DEFAULT);
echo $hash;
На выходе вы получите длинную строку. Именно её и нужно сохранять в базе данных вместо исходного пароля.
Что делает password_hash()
Функция password_hash() создаёт безопасный хеш пароля. Важный момент: она автоматически добавляет соль. Поэтому два одинаковых пароля почти всегда дадут разные хеши:
<?php
$password = 'secret123';
echo password_hash($password, PASSWORD_DEFAULT) . PHP_EOL;
echo password_hash($password, PASSWORD_DEFAULT) . PHP_EOL;
Новичков это иногда пугает: «Как тогда сравнивать пароль?» Сравнивать хеши вручную не нужно. Для этого есть password_verify().
Как проверить пароль через password_verify()
При входе пользователь вводит пароль. Вы берёте хеш из базы данных и передаёте оба значения в password_verify():
<?php
$passwordFromForm = 'secret123';
$hashFromDatabase = '$2y$10$exampleExampleExampleExampleExampleExampleExample';
if (password_verify($passwordFromForm, $hashFromDatabase)) {
echo 'Пароль верный';
} else {
echo 'Неверный пароль';
}
В реальном проекте хеш будет получен из базы данных по email, логину или ID пользователя.
Пример регистрации пользователя
Ниже упрощённый пример обработки формы регистрации. Главное — перед сохранением пароля вызвать password_hash():
<?php
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
if ($email === '' || $password === '') {
exit('Заполните email и пароль');
}
if (strlen($password) < 8) {
exit('Пароль должен быть не короче 8 символов');
}
$passwordHash = password_hash($password, PASSWORD_DEFAULT);
// Далее $passwordHash сохраняется в базу данных,
// например в поле password_hash.
echo 'Пользователь зарегистрирован';
Поле в базе данных лучше назвать не password, а password_hash. Так понятнее, что там хранится не исходный пароль.
Пример входа пользователя
При авторизации алгоритм такой: найти пользователя по email, получить его хеш пароля, проверить введённый пароль через password_verify().
<?php
$email = trim($_POST['email'] ?? '');
$password = $_POST['password'] ?? '';
// Допустим, эти данные пришли из базы данных.
$user = [
'id' => 15,
'email' => 'user@example.com',
'password_hash' => password_hash('secret123', PASSWORD_DEFAULT),
];
if (!$user) {
exit('Пользователь не найден');
}
if (!password_verify($password, $user['password_hash'])) {
exit('Неверный email или пароль');
}
session_start();
$_SESSION['user_id'] = $user['id'];
echo 'Вы вошли';
Обратите внимание на сообщение об ошибке. В реальном проекте часто лучше писать одинаково: Неверный email или пароль. Так вы не подсказываете злоумышленнику, существует ли такой email.
PASSWORD_DEFAULT или PASSWORD_BCRYPT?
В большинстве случаев используйте PASSWORD_DEFAULT:
<?php
$hash = password_hash($password, PASSWORD_DEFAULT);
Это рекомендуемый вариант для обычных проектов. PHP сам выберет актуальный алгоритм по умолчанию. Сейчас часто используется bcrypt, но в будущем значение может измениться. Поэтому важно выделять в базе достаточно места под хеш: обычно используют VARCHAR(255).
Если вам нужно явно использовать bcrypt, можно написать так:
<?php
$hash = password_hash($password, PASSWORD_BCRYPT);
Настройка cost: когда это нужно
Для bcrypt можно задать параметр cost. Чем он выше, тем медленнее создаётся хеш. Это усложняет перебор паролей, но увеличивает нагрузку на сервер.
<?php
$hash = password_hash($password, PASSWORD_BCRYPT, [
'cost' => 12,
]);
Не ставьте слишком большое значение «на всякий случай». Проверьте скорость на вашем сервере. Хороший ориентир: хеширование одного пароля должно занимать заметное, но приемлемое время, например десятки или сотни миллисекунд, а не несколько секунд.
Как обновлять старые хеши
PHP умеет проверять, не устарел ли хеш. Для этого есть password_needs_rehash(). Это полезно, если вы изменили алгоритм или параметры cost.
<?php
if (password_verify($password, $user['password_hash'])) {
if (password_needs_rehash($user['password_hash'], PASSWORD_DEFAULT)) {
$newHash = password_hash($password, PASSWORD_DEFAULT);
// Обновите password_hash пользователя в базе данных.
}
echo 'Успешный вход';
}
Так можно постепенно обновлять безопасность без принудительного сброса паролей всем пользователям.
Типичные ошибки новичков
- Хранить пароль в открытом виде — самая опасная ошибка.
- Использовать md5 или sha1 — эти функции не подходят для паролей.
- Сравнивать хеши вручную — используйте только password_verify().
- Обрезать хеш в базе — используйте поле достаточной длины, например VARCHAR(255).
- Отправлять пароль обратно пользователю — при восстановлении пароля нужно создавать ссылку или токен сброса, а не высылать старый пароль.
Минимальная структура таблицы
Для старта таблица пользователей может выглядеть так:
CREATE TABLE users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(190) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
created_at DATETIME NOT NULL
);
В реальном проекте добавляют поля статуса, роли, даты обновления, токены подтверждения email и другие данные.
Практические рекомендации
- Проверяйте минимальную длину пароля, например от 8 или 10 символов.
- Не ограничивайте пароль слишком жёстко: пользователи должны иметь возможность использовать длинные фразы.
- Всегда используйте HTTPS на сайте с авторизацией.
- После входа сохраняйте в сессию ID пользователя, а не весь объект пользователя и не пароль.
- Для запросов к базе используйте подготовленные выражения, чтобы не получить SQL-инъекцию.
Если вы хотите не просто выучить отдельные функции, а собрать полноценную регистрацию, авторизацию, работу с MySQL и защиту проекта на практике, посмотрите курс PHP и MySQL с нуля до уверенной разработки — он хорошо дополняет эту тему.
Итог
password_hash() и password_verify() — базовый минимум для безопасной работы с паролями в PHP. При регистрации создавайте хеш и сохраняйте его в базу. При входе проверяйте пароль через password_verify(). Не используйте md5, не храните пароли открытым текстом и заранее выделяйте достаточно места под хеш в таблице пользователей.
-
Создано 03.07.2026 17:00:49
-
Михаил Русаков

Комментарии (0):
Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.