对于我的项目,我需要一个“忘记密码”功能。

我还不确定如何实现这种功能,所以我希望在互联网上找到一些“最佳实践”,但是找不到任何有用的方法来解决这个问题的每个重要方面。常见功能。


我自己对此的想法很简单:

如果用户想要更改密码,我可以创建一个附加的唯一令牌uniqueTokenForTheUser一个“更改密码请求”,从本质上讲就是我的后端的标识符,以告诉我发送请求的用户是否是正确的用户。

因此,例如,我将生成/发送电子邮件至user@example.com链接

http://www.example.com/changePassword?token=uniqueTokenForTheUser


uniqueTokenForTheUser将存储在一个表中,该表将在某个时间间隔内由线程检查,并在令牌过期后删除记录(如果用户这样做)并没有实际更改他的密码。

尽管这听起来很简单,但我想仔细检查一下是否存在“最佳做法”,例如。G。当涉及到特定令牌的生成和删除时。

欢迎任何建议或对文章/教程的引用! br />


基于表单的网站身份验证的权威指南(感谢Krumia)


评论

左字段选项,但是您可能要考虑不处理用户名/密码帐户信息,而是将其发送给第三方(即,如何通过Google / FB / etc登录到Stack Exchange)。 />
@DavidGrinberg如果需要考虑隐私问题,那么OpenId很棒,可以完成所有事情。

@ wizzwizz4但是它有基本的算术插件吗?

必须阅读:基于表单的网站身份验证的权威指南

@DavidGrinberg就我而言,我正在开发一项需要付款的服务。我不确定人们是否愿意使用他们的Facebook帐户登录他们要付费的服务,但我在这里可能完全错了。

#1 楼

仅为此使用HTTPS,然后我们将介绍实现的详细信息。

首先,您将要防止用户枚举。

,请不要在页面上显示该用户是否存在。这仅应在电子邮件本身中公开。

其次,您将要避免引荐来源网址泄漏。确保目标链接上没有外部链接或外部资源。缓解此问题的一种方法是在跟随初始链接后进行重定向,以使令牌不再位于查询字符串中。请注意,如果出现问题(例如,数据库暂时关闭),并且显示了标准错误模板,则如果该令牌包含任何外部引用,则可能会导致该令牌泄漏。

生成一个具有CSPRNG的128位熵的令牌。使用SHA-2存储此服务器端,以防止重置表上的任何数据泄漏漏洞都允许攻击者重置密码。请注意,不需要盐。在短时间(例如几个小时)后将这些令牌过期。

除了在电子邮件链接中向用户提供未哈希的令牌外,还为用户提供了浏览页面的选项手动,然后粘贴令牌值。默认情况下,这可以防止查询字符串值记录在浏览器历史记录以及任何代理和服务器日志中。

或者,您可能要确保启动密码的会话的会话标识符重置是跟随链接的那个。这可以帮助保护攻击者可以访问用户电子邮件的帐户(例如,设置对电子邮件帐户的访问权限受限的快速转发全部规则)。但是,所有这些操作的真正目的是防止攻击者在用户请求重置后进行机会性攻击-如果攻击者想要定位到您的特定站点,攻击者仍可以为受害者请求自己的重置令牌。一旦密码已重置为用户的选择之一,您将需要使令牌失效并向用户发送电子邮件,以告知他们发生了这种情况,以防万一攻击者设法以某种方式重置了密码(无需控制)邮件帐户)-深入防御。您还应该旋转当前会话标识符,并使该用户帐户的其他会话失效。
这消除了用户必须再次登录的需要,同时清除了攻击者绕过的所有会话,尽管有些用户喜欢该站点将其注销,以便他们得到确认信息,确认他们的密码已被重置。重定向到登录页面还使一些密码管理器有机会保存登录URL和新密码,尽管许多人已经从重置页面检测到新密码。

您可能还希望考虑其他带外选项,用于重置机制和更改通知。例如,通过短信或手机警报。

评论


我要补充:更改密码后,请勿立即登录用户。使所有会话无效,并将他路由到登录页面。有几个站点可以这样做,这是一个较小的漏洞。

– Mindwin
16 Mar 18 '16 at 13:32

请注意扩展-如果该网站登录用户会带来什么风险?

– SilverlightFox
16年3月18日在13:53

@SilverlightFox如果有人找到了您的密码并登录到您的帐户,并且该站点没有使会话令牌无效,则不会以欺诈方式登录用户。通过使所有会话无效,这确保了使用您的帐户的所有其他用户必须重新输入登录凭据才能获得访问权限。

– sethmlarson
16 Mar 18 '16 at 14:32

如链接的答案所述,@oas不会旋转会话标识符吗?

– SilverlightFox
16 Mar 18 '16 at 14:54

从UX的角度来看,当我必须重设密码时,我想立即再次登录以“记住”该密码,并确定该密码已更改并且知道该更改的内容。

– Todd Wilcox
16年3月18日在16:39

#2 楼

您的思路是正确的。但是,我建议您从一个步骤开始,描述忘记密码功能的流程。有人声称忘记了密码,您需要确保标识此人确实是将为其启动密码恢复过程的帐户的所有者。

以下流程假定提供了以下服务:人们可以注册自己,例如网站(换句话说,可以使用注册功能建立注册电子邮件和/或用户名的列表)。

第一步:识别用户


点击“糟糕,我忘记了密码”链接,向用户显示一个表单,供他们输入用户名和电子邮件地址(也可以在表单中提示他们有关电子邮件地址的提示) of:'s ..... @ o .... com');
通知他们输入的电子邮件地址是否属于他们输入的用户名(是或否);
如果输入用户名和密码匹配,继续下一步。

第二步:开始恢复过程


生成随机恢复令牌(128位应该可以);
存储的哈希此令牌(使用密码哈希算法创建),以及在数据库中的创建时间戳记;
向用户发送一封电子邮件,其中包含指向更改密码表单的链接(包含恢复令牌)。更改密码表单的URL应该为HTTPS。
当您收到更改密码请求时,请检查:[1]。令牌的有效性(使用其创建时间与当前时间进行比较,通常10分钟的时间窗口就足够了); [2]。如果提供的令牌正确(对令牌进行哈希处理,则将生成的哈希与数据库中的哈希进行比较,就像输入密码一样);
如果所有检查都通过,则继续下一步。

第三步:更新密码


销毁您可能为此用户存储的所有“记住我”信息;
销毁与此用户关联的所有活动会话;
更新用户密码;
有选择地向他们的电子邮件地址发送电子邮件,通知他们更改;
登录用户。 >

评论


这个答案值得更多的投票!

– Stefan Falk
16年5月21日在11:44

我认为您的第1步会让您容易受到电子邮件枚举的影响,而您绝对不希望这样做。尽管似乎告诉他们电子邮件不匹配对用户来说很友好,但它是脚本和机器人的吸引人,它们希望将十亿个泄漏的电子邮件地址缩小到可以在您的网站上使用的地址。

–亚历克斯·怀特
17年12月12日在10:43

@AlexWhite,答案是基于用户可以注册自己的假设而写的(如答案中所示)。鉴于此,可以通过滥用注册功能来进行电子邮件枚举(请参阅答案)。考虑到这一限制,给定的方案得到了充分的保护。

–雅科
17-12-12在12:19



#3 楼

您的方法接近最佳实践。可能会有一个小的补充:


您可能要求用户名与令牌匹配,而不是仅仅从令牌中扣除用户。
您应该使用https而不是http 。

其他问题:关于生成:生成它们的通常方法是使用UUID,但是正如指出的那样,您应该使用完全随机且足够长的字符串。
关于删除:您可以按照建议定期清理未使用的旧令牌。也许使用一个允许邮件通过常规电子邮件灰名单的时间范围,例如15分钟。


评论


嗨!谢谢您的回答! HTTPS://和将令牌与用户名匹配都非常有用。阅读您的答案后,您会意识到令牌实际上也可以具有类型。例如CHANGE_PW和REGISTER。这样,我可以将一个表用于不同的电子邮件验证任务。那有意义吗? :)

– Stefan Falk
16年3月18日在11:13

当然。增加可用的“空间”-或减少其中的有效令牌始终是有意义的。但是请记住,在使用UUID时,您会拥有很大的空间,因此这可能不值得实现。

– Tobi Nary
16 Mar 18 '16 at 11:16

请注意,UUID对此是一个不好的选择-请参阅GUID设计为唯一而不是随机的。最好使用CSPRNG生成128位令牌。

– SilverlightFox
16 Mar 18 '16 at 11:40

@SilverlightFox,谢谢。真可惜我确实编辑了答案。

– Tobi Nary
16 Mar 18 '16在11:42

好的,谢谢!根据投票的数量,我想我也必须接受SilverlightFox的投票,但我也愿意接受+1 :)

– Stefan Falk
16年3月18日在18:14

#4 楼

关于此的一些想法:


电子邮件本质上是不安全的。攻击者可能会将令牌窃取到服务器与用户收件箱之间的任何位置。如果可能,请考虑使用另一种通信媒介,例如SMS。
如果通过电子邮件发送邮件,则还原链接应通过HTTPS而非HTTP进行。至少可以加密该过程的一部分。
为了防止用户枚举攻击,您可能希望显示相同的消息,无论用户输入的用户名/电子邮件地址是否存在。 (至少在用户仅输入用户名之后,不要显示电子邮件错误。)
使用良好的伪随机数生成器和长令牌。没有人应该能够猜出令牌。为了使令牌猜测更加困难,要求用户同时输入用户名和令牌。限制尝试次数(每个用户名和/或IP)也可以防止暴力破解。也许也是验证码?
您想限制令牌有效的时间。如果电子邮件卡在过滤器中,它可能会变慢,但我看不出有谁会需要半个小时以上的时间。
还原帐户后,请终止该帐户的所有旧会话。用户可能想要还原该帐户,因为该帐户已遭到破坏,然后应该注销攻击者。
仅发送一个使用令牌,而不发送新密码!永远不要通过电子邮件发送密码。
只允许一次使用令牌!使用该密码后,请立即将其删除(即使用户实际上并未更改密码)。

有关该主题的更多信息,我建议使用Troy Hunt。

评论


从理论上讲,允许用户只加载一次页面是好的,但对于某些用户来说可能会破坏事情。 GET请求(即您的链接将是的请求)应该是幂等的,这意味着当第二次调用它时,它应该给出相同的结果。在处理写得不好的缓存或其他问题时,这一点很重要:brian.pontarelli.com/2006/05/02/…

–帕特里克M
16 Mar 20 '16 at 5:40

哎呀我的意思是代理写得不好,而不是缓存。但是,具有Internet连接且正在丢弃数据包的用户可能会遇到相同的问题。

–帕特里克M
16 Mar 20 '16 at 5:50

短信也不安全!如果您担心电子邮件安全,那么最好使用2FA的Authenticator应用程序之一。严肃地说,如果某人的电子邮件遭到入侵,那对他们来说就是一场恶梦。

–亚历克斯·怀特
17年12月12日在10:56