Реализация аутентификации пользователя безопасно , не полагаясь на каркас (или стороннюю библиотеку, такую как OpenID), чтобы сделать это для вас, не является тривиальным обязательством.
При обзоре в 10 000 футов вы должны решить:
- У вас есть имена пользователей, адреса электронной почты или идентификаторы пользователей в качестве основного селектора?
- Как хранить пароли? PROTIP:
password_hash()
или scrypt - это путь.
- Как вы должны обрабатывать флажки "помни меня"? В Интернете существует множество плохих стратегий для этого. Относитесь к каждому из них со скептицизмом, поскольку они могут создавать уязвимости в вашем приложении.
- Как приложение должно обрабатывать пользователей, которые забыли свой пароль?
Информация в этом ответе актуальна и актуальна по состоянию на 9 мая 2015 г. и может быть устаревшей в связи с завершением конкурса по хешированию паролей
Первичные селекторы
Как правило, имена пользователей и адреса электронной почты лучше, чем идентификационные номера.
Не должно быть никаких требований безопасности, чтобы сохранить имена пользователей в секрете, потому что на практике они будут просочиться, когда кто-то попытается зарегистрироваться.
Вы можете решить, следует ли рассматривать адреса электронной почты как секрет. Обычно пользователям нравится не подвергаться воздействию спамеров, мошенников и троллей.
Хеширование пароля
Вам следует использовать password_hash()
и password_verify()
, если вы не обладаете достаточным опытом написания криптографических библиотек, чтобы идти дальше и выше.
За пределами Bcrypt
Иногда разработчикам нравится проявлять творческий подход (например, добавление «перца», что обычно означает предварительное хеширование или пароли HMAC со статическим ключом) и выходить за рамки стандартных реализаций. Мы сами сделали это, но очень консервативно.
Для наших внутренних проектов (которые имеют гораздо более высокий предел безопасности, чем блоги большинства людей), мы написали обертку вокруг этого API под названием PasswordLock
, которая сначала хэширует пароль с sha256
, затем base64 кодирует исходный хеш-код, затем передает этот хэш в кодировке base64 на password_hash()
и, наконец, шифрует хеш bcrypt с помощью правильно реализованной библиотеки шифрования .
Повторим, вместо перечеркивания мы шифруем наши хэши паролей. Это дает нам большую гибкость в случае утечки (мы можем расшифровать, а затем повторно зашифровать, потому что мы знаем ключ). Кроме того, мы можем запустить наш веб-сервер и базу данных на отдельном оборудовании в одном центре обработки данных, чтобы уменьшить влияние уязвимости внедрения SQL. (Чтобы начать взламывать хэши, вам нужен ключ AES. Вы не можете получить его из базы данных, даже если сбежите в файловую систему.)
// Storage:
$stored = \ParagonIE\PasswordLock\PasswordLock::hashAndEncrypt($password, $aesKey);
// Verification:
if (\ParagonIE\PasswordLock\PasswordLock::decryptAndVerify($password, $stored, $aesKey)) {
// Authenticated!
}
Хранение пароля с PasswordLock
:
hash('sha256', $password, true);
base64_encode($step1);
password_hash($step2, PASSWORD_DEFAULT);
Crypto::encrypt($step3, $secretKey);
Подтверждение пароля с помощью PasswordLock
:
Crypto::decrypt($ciphertext, $secretKey);
hash('sha256', $password, true);
base64_encode($step2);
password_verify($step3, $step1);
Дальнейшее чтение