Рекомендации PHP для аутентификации пользователей и безопасности паролей

Каковы лучшие текущие библиотеки / методы для аутентификации пользователей без использования CMS или тяжелой структуры?

Ответы должны включать предложения для всего, что, по вашему мнению, следует считать стандартом для новой разработки PHP, включающей аутентификацию пользователя.

Related of "Рекомендации PHP для аутентификации пользователей и безопасности паролей"

OpenID – это метод аутентификации пользователей на основе существующих учетных записей на общих веб-сервисах, таких как Yahoo, Google и Flickr.

Вход на ваш сайт основан на успешном входе на удаленный сайт.

Вам не нужно хранить конфиденциальную информацию пользователя или использовать SSL для защиты пользователей.

Текущую версию библиотеки PHP можно найти здесь .

Я использую OpenID .

Но, как stackoverflow, я использую openid-селектор проекта Google для тяжелого подъема.
Демо-страница здесь .

Очевидные преимущества (OpenID).

  • Вам не нужно быть экспертом по безопасности.
  • Пользователи доверяют большие сайты своей информацией.
  • Вы можете запросить такие вещи, как (псевдоним и т. Д.), Но пользователь должен выбрать.
  • Вам не нужно беспокоиться:
    • процессы регистрации
    • потерянный / забытый пароль

Безопасное внедрение аутентификации пользователей, не полагаясь на структуру (или стороннюю библиотеку, такую ​​как OpenID), чтобы сделать это для вас, не является тривиальной задачей.

При обзоре 10000 футов вам нужно решить:

  • У вас есть имена пользователей, адреса электронной почты или идентификаторы пользователей в качестве первичного селектора?
  • Как хранить пароли? PROTIP: password_hash() или scrypt – путь.
  • Как вы должны обрабатывать флажки «помнить меня»? В Интернете есть много плохих стратегий. Рассматривайте каждого из них скептически, потому что они могут вводить уязвимости в ваше приложение.
  • Как приложение должно обрабатывать пользователей, которые забывают пароль?

Информация, содержащаяся в этом ответе, актуальна и актуальна по состоянию на 9 мая 2015 года и может быть устарела после заключения конкурса хеширования пароля

Первичные селектора

В общем, имена пользователей и адреса электронной почты лучше, чем идентификационные номера.

Не должно быть никаких требований к безопасности, чтобы держать имена пользователей в секрете, потому что на практике они будут просочиться, когда кто-то попытается зарегистрироваться в любом случае.

Вы можете решить, следует ли рассматривать почтовые адреса как секрет. Обычно пользователи не подвергаются воздействию спамеров, мошенников и троллей.

Хеширование паролей

Вы должны использовать password_hash() и password_verify() если у вас недостаточно опыта написания криптографических библиотек, чтобы идти выше и выше.

Вне Bcrypt

Иногда разработчикам нравится создавать креатив (например, добавлять «перец», который обычно означает предварительное хеширование или HMACing пароли со статическим ключом) и выходит за рамки стандартных реализаций. Мы сами это сделали, но очень консервативно.

Для наших внутренних проектов (которые имеют гораздо более высокий уровень безопасности, чем блоги большинства людей) мы написали обертку вокруг этого API под названием PasswordLock которая сначала хеширует пароль с помощью sha256 , затем base64 кодирует исходный хеш-вывод, а затем передает этот base64-кодированный hash to password_hash() и, наконец, шифрует хэш-код bcrypt с правильно реализованной библиотекой шифрования .

Повторяем, вместо того , чтобы нагромождать, мы шифруем хэши паролей. Это дает нам большую гибкость в случае утечки (мы можем расшифровать, а затем снова зашифровать, потому что мы знаем ключ). Кроме того, мы можем запускать наш веб-сервер и базу данных на отдельном оборудовании в одном центре данных, чтобы уменьшить влияние уязвимости SQL-инъекции. (Чтобы начать хеширование трещин, вам нужен ключ AES. Вы не можете получить его из базы данных, даже если вы уйдете в файловую систему.)

 // Storage: $stored = \ParagonIE\PasswordLock\PasswordLock::hashAndEncrypt($password, $aesKey); // Verification: if (\ParagonIE\PasswordLock\PasswordLock::decryptAndVerify($password, $stored, $aesKey)) { // Authenticated! } 

Хранилище PasswordLock с PasswordLock :

  1. hash('sha256', $password, true);
  2. base64_encode($step1);
  3. password_hash($step2, PASSWORD_DEFAULT);
  4. Crypto::encrypt($step3, $secretKey);

Проверка PasswordLock с помощью PasswordLock :

  1. Crypto::decrypt($ciphertext, $secretKey);
  2. hash('sha256', $password, true);
  3. base64_encode($step2);
  4. password_verify($step3, $step1);

Дальнейшее чтение

  • Проблема безопасности: объединение Bcrypt с другими хэш-функциями
  • password_hash
  • password_verify
  • password_compat (для PHP <5.5.0)

Здесь много замечательных ответов, но я чувствую, что стоит это сказать – НЕ пытайтесь изобрести колесо в этом случае! Очень легко повредить аутентификацию пользователя различными способами. Если вам действительно не нужно индивидуальное решение, и у вас есть четкое знание схем безопасности и передовой практики, вы почти наверняка будете иметь недостатки безопасности.

OpenID отлично, или если вы собираетесь сворачивать свои собственные, по крайней мере, используйте созданную библиотеку и следуйте документации!

PHPass – это облегченная библиотека переменных хэширования с переменной стоимостью, использующая bcrypt.

Переменная стоимость означает, что вы можете впоследствии увеличить «стоимость» хеширующих паролей, чтобы обеспечить беспрепятственное повышение безопасности без необходимости аннулировать ранее испорченные пароли пользователей.

Размер поля, используемый для хранения хэшей, является постоянным даже при увеличении «стоимости» из-за увеличения не размера хэша, а количества итераций, необходимых для его создания.

Вход через HTTP AUTH

  1. Использование Apache: http://httpd.apache.org/docs/2.2/howto/auth.html
  2. Это также возможно с IIS и другими веб-серверами .

После аутентификации для PHP вам просто нужно использовать $_SERVER['PHP_AUTH_USER'] для получения имени пользователя, используемого во время аутентификации.

Это может быть более быстрым, а иногда и более гибким решением, чем обработка решения на уровне сценариев при условии, что для пользователя требуется ограниченная информация, так как все, что доступно вам, – это имя пользователя, используемое для входа в систему.

Однако забудьте об интеграции вашей аутентификации в формате HTML, если вы не реализуете полную схему HTTP AUTH с языка скриптов (как описано ниже).

Перемещение собственного HTTP-AUTH на вашем языке сценариев

Фактически вы можете расширить HTTP Basic Auth , эмулируя его на своем языке сценариев. Единственным требованием для этого является то, что ваш язык сценариев должен иметь возможность отправлять HTTP-заголовки HTTP-клиенту. Подробное объяснение того, как выполнить это с помощью PHP, можно найти здесь: ( подробнее об PHP и HTTP AUTH ).

Вы можете перейти к статье выше, используя типичную схему аутентификации, хранилище файлов, даже сеансы PHP или файлы cookie (если информация не нужна, чтобы быть постоянной), предоставляя вам большую гибкость при использовании HTTP AUTH, но при этом сохраняя некоторую простоту.

Недостатки HTTP AUTH

  1. Основной недостаток HTTP-аутентификации – это осложнения, которые могут возникнуть при регистрации. Основной способ очистить сеанс пользователя – закрыть браузер или передать заголовок с 403 аутентификацией. К сожалению, это означает, что всплывающее сообщение HTTP AUTH возвращается на страницу, а затем требует, чтобы пользователи либо вошли в систему, либо удалили отмену. Это может не сработать при учете удобства использования, но может быть обработано с некоторыми интересными результатами (т. Е. С использованием комбинации файлов cookie и HTTP AUTH для хранения состояния).

  2. Обработка HTTP-заголовков HTTP, сеанса и HTTP-заголовков определяется реализацией браузера стандартом. Это означает, что вы будете придерживаться этой реализации (включая любые ошибки) без возможности обхода (в отличие от других альтернатив).

  3. Базовый auth также означает, что auth_user и пароль отображаются в журналах сервера, а затем вы должны использовать https для всего, потому что иначе имя пользователя и пароль также передаются по сети при каждом запросе в виде простого текста.

Важно отделить уровень безопасности вашего приложения от остальной части. Если между вашей логикой приложения и вашей системой связи нет расстояния, вы можете свободно общаться в одном месте и безопасно где-то в другом месте. Возможно, вы совершите ошибку и отправьте пароль в незашифрованном файле cookie, или, может быть, вы забудете подтвердить учетные данные пользователя за один шаг. Без «правильного пути» для общения с пользователем вы обязательно ошибетесь.

Например, предположим, что теперь вы проверяете пользователей:

 user_cookie = getSecureCookie() if (user_cookie.password == session_user.password) { do_secure_thing() ... } 

Если в getSecureCookie () обнаружена уязвимость, и вы используете этот код для проверки пользователей во всем приложении, вы можете не найти все экземпляры getSecureCookie (), которые необходимо устранить. Если, однако, вы отделите свою логику от своей безопасности:

 if (userVerified()) { do_secure_thing() ... } 

… вы сможете быстро и легко восстановить свою заявку. Дайте себе «правильный путь» для обеспечения безопасности, и вы значительно реже сделаете серьезную ошибку безопасности.

Лучшая проверка подлинности – это использование многофакторной аутентификации, в идеале – без токенов во всех безопасных входах.

Защита паролем и более простая в использовании с высокой надежностью и безопасностью. Есть несколько доступных за пределами EMC / RSA. Я предпочитаю PINSafe SwivelSecure.

Игорь S