Лучшие практики для кодов электронного письма с подтверждением

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

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

md5("xxxxxxxxx".$username."xxxxxxxxxxx".$timestamp."xxxxxxxxx");

Где $timestamp относится ко времени пользовательского создания. В целом я был вполне доволен этим, но тогда я добрался до взглядов, это достаточно безопасно? И что относительно возможности коллизий? И я также должен сгенерировать коды для сброса пароля, и т.д. Если бы я использовал подобную методологию, то коллизия могла бы привести к одному пользователю, непреднамеренно изменяющему пароль другого пользователя. И это бесполезно.

Так как дела эти вещи? Мои мысли были таблицей следующего формата:

codePK (int, a-I), userID (int), type (int), code (varchar 32), date (timestamp)

Где 'тип' был бы 1, 2 или 3 значения "активация", "почтовое изменение" или "сброс пароля". Действительно ли это - хороший способ сделать его? У Вас есть лучший путь?

Используя метод, подобный вышеупомянутому, я мог автоматически удалить что-нибудь более чем два дня, не используя задания крона? Мой хост (nearlyfreespeech.net) не поддерживает их. Если бы вообще возможный я хотел бы постараться не иметь задание крона на внешнем хосте, какой wget's сценарий, который удаляет вещи, поскольку это - просто грязный =P.

Спасибо!
Mala

Обновление:
Разъясниться: я понял единственный путь к надежно и безопасно иду об этой задаче, при помощи базы данных, которая является тем, чего старалась избегать исходная функция. Мой вопрос идет как таблица (или таблицы?) должен быть структурирован. Кто-то предложил, чтобы я покончил с codePK и просто сделал код PK. Таким образом короче говоря, мой вопрос: это то, что Вы делаете?

15
задан phidah 9 January 2010 в 13:13
поделиться

5 ответов

[

] Когда мне нужны такие трюки, это, как правило, одна из двух причин, обе из которых упомянуты вами: [

] [
    ] [
  1. ]В качестве ключа, используемого для верификационных писем, отправляемых пользователю[
  2. ] [
  3. ]В качестве ключа, используемого для ссылок сброса пароля[
  4. ] [
] [

]Конечно, было бы много других случаев, когда вы бы рассмотрели возможность использования такой конструкции. [

] [

]Прежде всего, вы всегда должны использовать какую-нибудь соль, которая скрыта и которую знаете только вы. Обратите внимание, что эта соль должна быть разной для каждого пользователя. Например, соль может быть рассчитана как []sha256(что-то случайное) []. Затем эта соль должна быть сохранена в базе данных вместе с именем пользователя и паролем (хэшированная с солью).[

] [

]Что бы я сделал при отправке ссылки на сброс пароля, я бы создал другую соль (не давайте пользователю доступ ни к чему, что хэшируется с вашей солью. Он знает свой пароль, поэтому, используя брутфорс, он потенциально может вычислить вашу соль). Другая соль, которая по сути является лишь хэшем случайной строки (возможно, вы захотите перейти на md5 здесь, так как вы упоминали, что длина - это проблема), если вы затем сохраните ее в своей базе данных.[

] [

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

] [

]Что это по сути сводится к следующему:[

] [
    ] [
  • ]Хэширование паролей ваших пользователей с помощью уникальной для пользователя соли ([]и[], возможно, глобальной, секретной соли).[
  • ] [
  • ]Генерация ключа путем хэширования ряда случайных или псевдослучайных источников, таких как метки времени, []mt_rand()[] или даже случайных. org, если вам действительно нужны случайные вещи.[
  • ] [
  • ]Никогда не используйте свою глобальную соль или соль, уникальную для пользователя, для хэширования чего-либо, к чему пользователь получает доступ, включая ключи сброса пароля, активационные ключи и т.д.[
  • ] [
] [

]Пожалуйста, не думайте, что я ни в коем случае не эксперт по безопасности, и, вероятно, я забыл несколько вещей, и, возможно, я упомянул некоторые очень плохие вещи из практики. Только мои 5 центов ;-)[

]
10
ответ дан 1 December 2019 в 04:40
поделиться
[

]Зачем использовать данные пользователя в качестве основы для ключа авторизации? [

] [

]Я предполагаю, что вы храните деактивированные данные в базе данных, так почему бы просто не добавить дополнительную запись, которая является просто случайным ключом (возможно md5'ed []uniqid[] с некоторыми дополнительными манипуляциями) и затем проверить это?[

].
2
ответ дан 1 December 2019 в 04:40
поделиться
[

] Это было достаточно безопасно вплоть до того момента, когда вы опубликовали свой метод в Интернете! Это потому, что вы полагались на безопасность по неясности, что не является хорошей идеей.[

] [

] Вы должны использовать некую хэш-функцию с ключом или MAC в идеале, который включает в себя секретный ключ, известный только вам.[

].
1
ответ дан 1 December 2019 в 04:40
поделиться
[

] Почему бы не попросить пользователя ввести имя пользователя [] и [] свой код, тем самым устранив любую проблему со столкновением? Вы не теряете ничего безопасного, так как все еще просите ключ, который они получат по электронной почте, но вы не дадите им возможность сбросить пароли других пользователей[

].
0
ответ дан 1 December 2019 в 04:40
поделиться
[

] Почему бы не сделать уникальный индекс кодового поля? Чтобы никогда не было коллизий?[

] [

]Также, если вам не нужно создавать хэш из пользовательского ввода и сопоставлять его с хэшем базы данных (подтверждение по электронной почте, сброс пароля и т.д.) - вы можете добавить случайную строку в тело хэша, такую как []md5('xxx'.$username.'xxx'.time().'xxx'.rand())[][

]
0
ответ дан 1 December 2019 в 04:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: