我正在使用ASP.NET中的一个应用程序,并且特别想知道Password Reset
如果我想实现自己的功能,我将如何实现一个功能.
具体来说,我有以下问题:
生成难以破解的唯一ID的好方法是什么?
应该连接一个计时器吗?如果是这样,它应该多久?
我应该记录IP地址吗?它甚至重要吗?
在"密码重置"屏幕下我应该要求哪些信息?只是电邮地址?或者也许是电子邮件地址加上他们"知道"的一些信息?(最喜欢的球队,小狗的名字等)
我还需要注意其他任何考虑因素吗?
注意:其他问题完全掩盖了技术实施.事实上,接受的答案掩盖了血腥的细节.我希望这个问题和随后的答案能够进入血腥的细节,我希望通过更加狭隘地表达这个问题,答案不是"绒毛"而是"血腥".
编辑:答案也将讨论如何在SQL Server中建模和处理这样的表或任何ASP.NET MVC链接到答案.
编辑2012/05/22:作为这个流行答案的后续,我不再在这个程序中使用GUID.与其他流行的答案一样,我现在使用自己的哈希算法生成要在URL中发送的密钥.这具有更短的优点.查看System.Security.Cryptography以生成它们,我通常也使用SALT.
首先,请勿在请求时立即重置用户密码.这是一个安全漏洞,因为有人可以猜到电子邮件地址(即您在公司的电子邮件地址)并随心所欲地重置密码.这些天的最佳做法通常包括发送到用户电子邮件地址的"确认"链接,确认他们想要重置它.此链接是您要发送唯一密钥链接的位置.我发送的链接如下:domain.com/User/PasswordReset/xjdk2ms92
是的,在链接上设置超时并在后端存储密钥和超时(如果使用的话,则为salt).超时3天是常态,并确保在用户请求重置时在网络级别通知用户3天.
我以前的回答说使用GUID.我现在正在编辑它以建议每个人使用随机生成的哈希,例如使用RNGCryptoServiceProvider
.并且,确保从哈希中消除任何"真实的单词".我记得一个特殊的早上6点的电话,其中一位女士在她的"假设是随机的"字样中收到了某个"c"字,这是开发人员所做的.卫生署!
用户点击"重置"密码.
要求用户发送电子邮件.
用户输入电子邮件并点击发送.不要确认或拒绝电子邮件,因为这也是不好的做法.简单地说,"如果电子邮件已经过验证,我们已经发送了密码重置请求." 或类似神秘的东西.
您可以从中创建哈希RNGCryptoServiceProvider
,将其作为ut_UserPasswordRequests
表中的单独实体存储并链接回用户.因此,您可以跟踪旧请求并通知用户旧链接已过期.
将链接发送到电子邮件.
用户获取链接http://domain.com/User/PasswordReset/xjdk2ms92
,然后单击它.
如果链接已验证,则要求输入新密码.很简单,用户可以设置自己的密码.或者,在此处设置您自己的隐秘密码,并在此处通知他们新密码(并通过电子邮件发送给他们).
这里有很多好的答案,我不打算重复这一切......
除了一个问题,这里几乎每个答案都重复,即使它错了:
Guids(实际上)是唯一的,统计上无法猜测.
事实并非如此,GUID是非常弱的标识符,不应该用于允许访问用户的帐户.
如果你检查一下这个结构,你最多总共得到128位...这在现在看来并不多.
其中前半部分是典型的不变量(对于生成系统),剩下的一半是时间依赖的(或类似的东西).
总而言之,它是一种非常脆弱且易于强制的机制.
所以不要使用它!
相反,只需使用加密强大的随机数生成器(System.Security.Cryptography.RNGCryptoServiceProvider
),并获得至少256位的原始熵.
所有其余的,正如众多其他答案所提供的那样.
首先,我们需要知道您对用户的了解.显然,你有一个用户名和一个旧密码.你还知道什么?你有电子邮件地址吗?你有关于用户最喜欢的花的数据吗?
假设您有用户名,密码和工作电子邮件地址,则需要在用户表中添加两个字段(假设它是一个数据库表):一个名为new_passwd_expire的日期和一个字符串new_passwd_id.
假设您拥有用户的电子邮件地址,当有人请求重置密码时,您将按如下方式更新用户表:
new_passwd_expire = now() + some number of days new_passwd_id = some random string of characters (see below)
接下来,您通过该地址向用户发送电子邮件:
亲爱的,某某
有人在<您的网站名称>上为用户帐户
请求了新密码.如果您确实要求重置密码,请点击以下链接: http://example.com/yourscript.lang?update= < new_password_id >
如果该链接不起作用,您可以访问http://example.com/yourscript.lang并在表单中输入以下内容:
如果您未请求重置密码,则可以忽略此电子邮件.
谢谢,亚达亚达
现在,编写yourscript.lang:这个脚本需要一个表单.如果在URL上传递了var更新,则表单只询问用户的用户名和电子邮件地址.如果未通过更新,则会询问用户名,电子邮件地址以及电子邮件中发送的ID代码.您还要求输入新密码(当然是两次).
要验证用户的新密码,请验证用户名,电子邮件地址和所有匹配的ID代码,请求未过期,以及两个新密码是否匹配.如果成功,则将用户密码更改为新密码,并清除用户表中的密码重置字段.还要确保将用户注销/清除任何与登录相关的cookie并将用户重定向到登录页面.
实质上,new_passwd_id字段是仅适用于密码重置页面的密码.
一个潜在的改进:您可以从电子邮件中删除
至于你的问题:
生成随机字符串:它不需要非常随机.任何GUID生成器甚至md5(concat(salt,current_timestamp()))都足够了,其中salt是用户记录上的内容,如创建时间戳帐户.它必须是用户看不到的东西.
计时器:是的,你需要这个只是为了让你的数据库保持理智.不超过一周是必要的,但至少2天,因为您永远不知道电子邮件延迟可能会持续多长时间.
IP地址:由于电子邮件可能会延迟数天,因此IP地址仅用于记录,而不用于验证.如果要记录它,请执行此操作,否则您不需要它.
重置屏幕:见上文.
希望涵盖它.祝好运.