Как выполнить сброс пароля?

Я работаю над приложением в ASP.NET и задаюсь вопросом, как я мог бы реализовать функцию Password Reset, если бы захотел свернуть свой.

В частности, у меня есть следующие вопросы:

  • Что такое хороший способ создания уникального идентификатора, который трудно взломать?
  • Должен ли быть установлен таймер? Если да, то как долго это должно быть?
  • Должен ли я записывать IP-адрес? Это даже имеет значение?
  • Какую информацию следует запрашивать на экране "Пароль Reset"? Просто адрес электронной почты? Или, может быть, адрес электронной почты плюс часть информации, которую они "знают"? (Любимая команда, имя щенка и т.д.)

Есть ли какие-либо другие соображения, о которых я должен знать?

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

Изменить. Ответы также будут рассмотрены в отношении того, как такая таблица будет смоделирована и обработана в SQL Server, или любые ссылки ASP.NET MVC для ответа будут оценены.

Ответ 1

Здесь много хороших ответов, я не буду повторять все это...

За исключением одного вопроса, который повторяется почти каждым ответом здесь, хотя его ошибка:

Гиды (реалистично) уникальны и статистически невозможно угадать

Это неверно, идентификаторы GUID являются очень слабыми идентификаторами и должны НЕ использоваться для разрешения доступа к учетной записи пользователя.
Если вы изучите структуру, вы получите в общей сложности 128 бит больше... что сегодня не считается много.
Из которого первая половина является типичным инвариантом (для генерирующей системы), а половина оставшихся зависит от времени (или что-то другое подобное).
В целом, это очень слабый и легко грубый механизм.

Так что не используйте это!

Вместо этого просто используйте криптографически сильный генератор случайных чисел (System.Security.Cryptography.RNGCryptoServiceProvider) и получите не менее 256 бит исходной энтропии.

Все остальное, как и многочисленные другие ответы.

Ответ 2

EDIT 2012/05/22: В ответ на этот популярный ответ я больше не использую GUID в этой процедуре. Как и в других популярных ответах, теперь я использую свой собственный алгоритм хеширования для генерации ключа для отправки URL. Преимущество этого также короче. Изучите System.Security.Cryptography, чтобы сгенерировать их, и я обычно использую SALT.

Во-первых, не сразу reset пароль пользователя.

Во-первых, не сразу reset пароль пользователя, когда он его запрашивает. Это нарушение безопасности, поскольку кто-то может угадать адреса электронной почты (т.е. Ваш адрес электронной почты в компании) и пароли reset по своему усмотрению. Лучшие практики в эти дни обычно включают ссылку "подтверждение", отправленную на адрес электронной почты пользователя, подтверждающий, что они хотят reset его. Эта ссылка предназначена для отправки уникальной ключевой ссылки. Я посылаю ссылку со ссылкой: domain.com/User/PasswordReset/xjdk2ms92

Да, установите тайм-аут в ссылке и сохраните ключ и тайм-аут на вашем сервере (и соль, если вы используете его). Тайм-ауты 3 дня являются нормой и не забудьте уведомить пользователя о 3 днях на веб-уровне, когда они запрашивают reset.

Используйте уникальный хеш-ключ

В моем предыдущем ответе было сказано, что нужно использовать GUID. Теперь я редактирую это, чтобы советовать всем использовать случайный хэш, например. используя RNGCryptoServiceProvider. И, не забудьте удалить любые "реальные слова" из хеша. Я вспоминаю специальный телефонный звонок 6am, где женщина получила определенное "c" слово в своем "предположительном случайном" хэшированном ключе, которое сделал разработчик. Doh!

Вся процедура

  • Пользователь нажимает "reset" пароль.
  • Пользователь запрашивает электронное письмо.
  • Пользователь вводит электронную почту и клики. Не подтверждайте или отклоняйте электронное письмо, так как это неправильная практика. Просто скажите: "Мы отправили пароль reset запрос, если электронное письмо подтверждено". или что-то загадочное.
  • Вы создаете хэш из RNGCryptoServiceProvider, сохраняете его как отдельный объект в таблице ut_UserPasswordRequests и ссылаетесь на пользователя. Таким образом, вы можете отслеживать старые запросы и информировать пользователя о том, что устаревшие ссылки истекли.
  • Отправьте ссылку на письмо.

Пользователь получает ссылку, например http://domain.com/User/PasswordReset/xjdk2ms92, и нажимает на нее.

Если ссылка подтверждена, вы запрашиваете новый пароль. Простой, и пользователь получает свой собственный пароль. Или, установите свой собственный секретный пароль здесь и сообщите им о своем новом пароле здесь (и напишите ему).

Ответ 3

Во-первых, нам нужно знать, что вы уже знаете о пользователе. Очевидно, что у вас есть имя пользователя и старый пароль. Что еще вы знаете? У вас есть адрес электронной почты? У вас есть данные о любимом цвете пользователя?

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

Предполагая, что у вас есть адрес электронной почты пользователя, когда кто-то запрашивает пароль reset, вы обновляете таблицу пользователя следующим образом:

new_passwd_expire = now() + some number of days
new_passwd_id = some random string of characters (see below)

Затем вы отправляете электронное письмо пользователю по этому адресу:

Дорогой так себе и так

Кто-то запросил новый пароль для учетной записи пользователя < имя пользователя > в < имя вашего сайтa > . Если вы запросили этот пароль reset, перейдите по этой ссылке:

http://example.com/yourscript.lang?update=<new_password_id >

Если эта ссылка не работает, вы можете перейти в http://example.com/yourscript.lang и ввести в форму следующее: < new_password_id >

Если вы не запрашивали пароль reset, вы можете игнорировать это письмо.

Спасибо, yada yada

Теперь, coding yourscript.lang: Это script нуждается в форме. Если обновление var прошло по URL-адресу, форма просто запрашивает имя пользователя и адрес электронной почты. Если обновление не передано, оно запрашивает имя пользователя, адрес электронной почты и код идентификатора, отправленный по электронной почте. Вы также запрашиваете новый пароль (дважды, конечно).

Чтобы проверить новый пароль пользователя, вы подтверждаете, что имя пользователя, адрес электронной почты и код идентификатора совпадают, что запрос не истек, и что два новых пароля совпадают. В случае успеха вы измените пароль пользователя на новый пароль и очистите поля пароля reset из таблицы пользователя. Также не забудьте зарегистрировать пользователя/очистить файлы cookie, связанные с подключением, и перенаправить пользователя на страницу входа.

По сути, поле new_passwd_id является паролем, который работает только на странице пароля reset.

Одно из возможных улучшений: вы можете удалить < имя пользователя > из письма. "Кто-то запросил пароль reset для учетной записи на этом адресе электронной почты...." Таким образом, делая имя пользователя чем-то, что только пользователь знает, если письмо перехвачено. Я не начинал так, потому что, если кто-то атакует учетную запись, они уже знают имя пользователя. Эта добавленная неясность останавливает атаки "человек в середине" в случае, если кто-то злонамеренно совершит перехват электронной почты.

Что касается ваших вопросов:

генерация случайной строки: она не должна быть чрезвычайно случайной. Любой GUID-генератор или даже md5 (concat (salt, current_timestamp())) достаточно, где соль - это что-то в записи пользователя, например, была создана учетная запись timestamp. Это должно быть то, что пользователь не может видеть.

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

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

Reset Экран: см. выше.

Надеюсь, что это покрывает. Удачи.

Ответ 4

Идентификатор GUID, отправленный на адрес электронной почты записи, скорее всего, подходит для большинства приложений, запущенных на заводе-изготовителе, с еще большим временем ожидания.

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

Ответ 5

Вы можете отправить электронное письмо пользователю со ссылкой. Эта ссылка будет содержать некоторую труднодоступную строку (например, GUID). На стороне сервера вы также сохраните ту же строку, что и вы отправили пользователю. Теперь, когда пользователь нажимает на ссылку, вы можете найти в своей записи db ту же секретную строку и reset свой пароль.

Ответ 6

1) Для генерации уникального идентификатора вы можете использовать алгоритм Secure Hash. 2) таймер прилагается? Вы имели в виду Expiry для ссылки reset pwd?  Да, вы можете установить истечение срока действия 3) Вы можете запросить дополнительную информацию, кроме emailId, для проверки.   Как дата рождения или некоторые вопросы безопасности 4) Вы также можете генерировать случайные символы и просить ввести это также вместе с  запрос.. чтобы убедиться, что запрос пароля не автоматизирован некоторыми шпионскими программами или такими вещами..