Всем привет! На прошлой неделе мы опубликовали первую часть данной статьи, чем вызвали нешуточный холивар.
Одной из главных претензий было отсутствие в статье упоминания password_hash
, как мы и обещали, вторую часть данного материала начнем как раз таки с хеширования пароля с помощью password_hash
. Также напоминаем о том, что написание данной статьи было навеяно запуском новой группы по курсу «Backend-разработчик на PHP», но к программе обучения данный материал отношения не имеет.
Подробнее о программе обучения можно будет узнать на дне открытых дверей, а на примере бесплатного вебинара по теме «ServerLess PHP», вы можете оценить формат проведения лекций.
Пожалуй на этом мы завершим и без того затянувшееся предисловие и перейдем непосредственно к статье.
Хеширование пароля с помощью password_hash
Эта функция создает хеш пароля в соответствии с теми параметрами, которые мы ей зададим. Она использует односторонний алгоритм.
Мы можем выбрать, какой тип алгоритма использовать, задав одну из констант по своему выбору:
PASSWORD_DEFAULT
из PHP 5.5 использует Bcrypt в качестве алгоритма по умолчанию. Однако с течением времени это изменяется по мере обнаружения новых, более безопасных алгоритмов либо иных факторов.PASSWORD_BCRYPT
создает хешcrypt()
. Обычно он содержит 60 символов, опознать его можно по идентификатору в формате "$2y$".PASSWORD-ARGON2I
Argon2 на данный момент является одним из наиболее безопасных алгоритмов хеширования. Он доступен только в том случае, если РНР был скомпилирован с Argon2.PASSWORD_ARGON2ID
Этот алгоритм хеширования также принадлежит к семейству Argon2 и задействует версию Argon2ID, а не I. Чтобы он работал, также необходимо, чтобы РНР был скомпилирован посредством Argon2.
У этой функции также есть необязательный параметр, который состоит из ассоциативного массива, принимающего несколько ключей в соответствии с выбранным алгоритмом.
Если вы предпочитаете использовать Bcrypt, ключ этой последовательности будет значением cost.
Если вы выберете алгоритм, который использует Argon2, ключами для ассоциативного массива будут: memory_cost
(целое число, указывающее максимальное количество памяти, необходимое для вычисления хэша), time_cost
(целое число, указывающее максимальное время, необходимое для вычисления хэша) и thread
(другое целое число, указывающее количество потоков, используемых при вычислении хэша).
Не указывайте параметр salt
в РНР 7.0, иначе получите предупреждение об устаревшем подходе.
Теперь мы знаем, какие элементы необходимы для использования функции password_hash()
. Давайте посмотрим, как ее прописывать.
echo password_hash("MySuperPass", PASSWORD_DEFAULT);
$2y$10$TLayAY8ZaAZ9FE50EylGYO9oEgrb7gsw1yzJemHdBu1gOQfyWrEUm
$options = ['cost' => 12,];
echo password_hash("MySuperPass", PASSWORD_BCRYPT, $options);
$2y$12$jhmTbxAuZXVtX2y.Jc8iy.dW/NENqVCeq2vuoFI9/oa4./YlzhpYO
echo password_hash('rasmuslerdorf', PASSWORD_ARGON2I);
$argon2i$v=19$m=1024,t=2,p=2$YzJBSzV4TUhkMzc3d3laeg$zqU/1IN0/AogfP4cmSJI1vc8lpXRW9/S0sYY2i2jHT0
Сначала рекомендуется протестировать эту функцию на ваших серверах и настроить параметр cost таким образом, чтобы исполнение функции отнимало менее 100 миллисекунд в интерактивных системах.
Скрипт в вышеприведенном примере поможет вам задать оптимальное значение cost для вашего аппаратного оборудования.
Верификация пароля пользователя
Вы дали пользователям возможность зарегистрироваться в вашем новом приложении, они могут ввести туда свой пароль, и вы прекрасно знаете, как с этим паролем обращаться.
Хешируя данные в соответствии с последними трендами безопасности, вы ничего не храните в зашифрованном виде, а ваш сервер спрятан в подвале 10-метровой глубины.
Что теперь?
Теперь вы должны позволить пользователям залогиниться в приложении. Для этого в РНР предусмотрена встроенная функция, которая проверяет соответствие пароля хешированной последовательности. Эта функция носит название password_verify()
. Работает она примерно вот так:
$hash = '$2y$07$BCryptRequires22Chrcte/VlQH0piJtjXl.0t1XkA8pw9dMXTpOq';
if (password_verify('rasmuslerdorf', $hash)) {
echo 'Пароль верен!';
} else {
echo 'Пароль не правильный!';
}
У нее есть два параметра, и оба должны иметь формат последовательности. Первый параметр — это пароль, который пользователь ввел в форму входа в аккаунт. Второй параметр — это непосредственно хешированные данные, с которыми мы будем сверяться.
В результате мы получим логическое значение, готовое к использованию в условных операциях. Таким образом, мы можем или пустить пользователя в приложение или сообщить ему, что что-то пошло не так.
Эта функция работает благодаря тому, что на предыдущем шаге (когда мы хешировали пароль), значение, вернувшееся от password_hash
, включало в себя используемый нами алгоритм, cost
и salt
.
Таким образом, нам доступна вся информация, необходимая для password_verify()
.
Алгоритм работы системы регистрации пользователей на РНР
Надеюсь, теперь вы понимаете, какие меры безопасности принимают РНР-разработчики при обращении с паролями.
Сначала необходимо проверить наличие post-запроса, а затем отобрать и подсчитать количество пользователей, чьи данные совпадают с введенными.
Если все прошло успешно, мы верифицируем пароль и отправляем пользователя на стартовую страницу. В противном случае, например, на Javascript выводим окно предупреждения с оповещением об ошибке.
Заключение
Теперь вы знаете, как обеспечить безопасность своему приложению и как правильно обращаться с паролями. Следование полезным рекомендациям — это не просто стандарт, который вы должны соблюдать, а путь развития, следовать которому должно быть приятно.
Осваивайте новые техники по аналогии с тем, как вы только что ознакомились. Добавляйте дополнительный функционал и экспериментируйте с кодом до тех пор, пока не получите отличные скиллы по веб-разработке — будь то РНР или любой другой язык, открывающий перед вами не менее широкие возможности!
Автор: Дмитрий