我正在用ASP.NET开发一个应用程序,我特别想知道,如果我想创建自己的Password Reset
函数,我该如何实现它。
具体地说,我有以下问题:
还有其他我需要注意的事项吗?
NB:Other questions拥有完整的glossed over技术实现。事实上,公认的答案掩盖了血淋淋的细节。我希望这条问题和随后的答案会深入到血淋淋的细节中,我希望通过将这条问题的措辞更狭隘,我希望答案不是那么“空洞”,而是更“血腥”。
MVC :如果回答还涉及到如何在 Server中建模和处理这样的表,或者任何指向答案的ASP.NET 链接,我们将不胜感激。
发布于 2009-04-02 21:55:24
这里有很多好的答案,我不再重复了……
除了一个问题,这里几乎每个答案都重复了这个问题,尽管它是错误的:
Guids (实际上)是唯一的,在统计上是不可能猜测的。
这不是真的,GUID是非常弱的标识符,应该使用而不是来允许访问用户的帐户。
如果你检查这个结构,你最多只能得到128位...这在当今并不多见。
其中前一半是典型的不变(对于生成系统),剩下的一半是时间依赖的(或其他类似的东西)。
总而言之,这是一种非常脆弱和容易受到暴力侵害的机制。
所以不要用那个!
相反,只需使用加密的强随机数生成器(System.Security.Cryptography.RNGCryptoServiceProvider
),并获得至少256bit的原始熵。
所有其他的,正如许多其他答案所提供的那样。
发布于 2009-03-30 20:29:21
编辑2012/05/22:作为这个流行答案的后续,我自己在这个过程中不再使用GUID。像其他流行的答案一样,我现在使用自己的散列算法来生成要发送到URL中的密钥。这也有更短的优点。查看System.Security.Cryptography以生成它们,我通常也使用SALT。
首先,不要立即重置用户的密码。
首先,当用户请求密码时,不要立即重置密码。这是一个安全漏洞,因为有人可能会猜测电子邮件地址(即您在公司的电子邮件地址),并随意重置密码。这些天的最佳实践通常包括向用户的电子邮件地址发送一个“确认”链接,确认他们想要重置它。此链接是您要将唯一密钥链接发送到的位置。我发送了我的链接,如下所示:domain.com/User/PasswordReset/xjdk2ms92
是的,在链接上设置一个超时时间,并将密钥和超时时间存储在你的后端(如果你正在使用的话,还要存储salt )。3天的超时是常态,当用户请求重置时,请确保在web级别通知3天。
使用唯一的哈希键
我之前的回答是使用GUID。我现在正在编辑这篇文章,建议大家使用随机生成的散列,例如使用RNGCryptoServiceProvider
。并且,确保从散列中删除任何“真正的单词”。我记得有一次早上6点的特殊电话,一位女士收到了开发人员在她的“假设是随机的”散列密钥中的某个"c“字。多!
整个过程
RNGCryptoServiceProvider
中创建一个散列,将其作为一个单独的实体存储在一个ut_UserPasswordRequests
表中,并链接回用户。这样你就可以跟踪旧的请求,并通知用户旧的链接已经expired.用户获取链接,如http://domain.com/User/PasswordReset/xjdk2ms92
,然后单击它。
如果链接通过验证,则要求输入新密码。简单,用户可以设置自己的密码。或者,在这里设置你自己的密码,并在这里通知他们他们的新密码(并通过电子邮件发送给他们)。
发布于 2009-03-30 19:58:26
首先,我们需要了解您已经知道的有关用户的信息。显然,您有一个用户名和一个旧密码。其他你还知道些什么?你有电子邮件地址吗?你有关于用户最喜欢的花的数据吗?
假设您有用户名、密码和工作电子邮件地址,您需要向用户表中添加两个字段(假设它是一个数据库表):一个名为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=>
如果链接不起作用,您可以转到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地址仅用于日志记录,而不用于验证。如果你想记录它,那就做吧,否则你就不需要它了。
重置屏幕:见上文。
希望这样就可以了。祝好运。
https://stackoverflow.com/questions/664673
复制相似问题