关于安全性:查看我的设计:网站的密码重置工具

Review my design: Password resetting facility for web site

当有人丢失密码时,他们单击丢失或忘记的密码链接。他们需要输入他们的电子邮件地址,然后回答他们自己的秘密问题。如果机密问题是正确的,将向他们发送一封电子邮件,其中包含一个在24小时后过期的链接。

发送电子邮件时,将在数据库表中输入一条记录,其中包含以下信息:-需要重置密码的人的电子邮件-密码重置将过期的小时-请求保留密码的时间已提交。

发送的链接将引导用户找到一个允许他们输入新密码的表单。在此表单中,他们需要输入他们的电子邮件地址和密码x2。

当他们单击Submit时,会对DB进行检查,以确保电子邮件有效(密码正在重置)且尚未过期(通过比较两个日期以查看是否已超过到期时间,即24小时)。

如果电子邮件有效且尚未过期,并且两个密码匹配并满足最低要求,则应用新密码。

成功时给出确认消息。

Q1。这是一个很好的密码恢复模式吗?Q2。如何确保发送到用户地址的链接是唯一的?没有人会得到同样的链接?因此,没有人可以直接进入密码重置页面,尝试不同的电子邮件,而是让每个需要重置的帐户都有自己的唯一URL,仅对该帐户有效。

关于第二季度:

我在想,当用户请求重置密码时,会生成一个随机的唯一ID,并存储在24小时后过期的同一个记录中。此随机唯一ID的列可以称为"rid"

将发送给用户的电子邮件中的链接将以结束?RID=XXXXXXXXXXXX

当用户在重置密码的页面中单击提交时,页面顶部的"rid"用于从数据库中获取相应的电子邮件地址,以将其与表单中的电子邮件地址进行比较。这样做可以确保每个密码重置案例都有自己的唯一URL,其他帐户无法使用该URL重置其密码。

这是可行的解决方案吗?

如有任何贡献或建议,将不胜感激。


最佳:好的。

  • 通过openid登录。更少的编码复杂性,更少的点击,更少的打字,更少的浪费时间。
  • 完成。问题是没有意义的。不用再担心了,已经有人解决了这个问题。
  • 有10亿个站点实施了10亿个认证方案,99.999%的情况下是不必要的。为什么我作为一个用户应该信任你作为一个开发人员,不把我的密码以纯文本的形式存储,或者泄露它,或者自己被黑客攻击?很少有人对每个网站使用不同的密码…好的。

    如果这不可能,那么make将尽可能地轻松:好的。

  • 我单击"忘记密码?"链接。如果我已经输入了电子邮件(例如,在尝试登录失败后),这将自动发送邮件。如果我没有输入密码,只需隐藏密码字段并告诉我这样做。不要重新加载或将我转发到其他页面。
  • 我用一些键(例如https://site.com/account/reset?key=a890ea8219175f890b7c123ee74a22)得到一个到的链接。一些独特的散列,绑定到我的帐户,在这么多小时后过期。尽可能使用SSL。
  • 我点击这个链接,你就可以通过这个键来获取我的账户详细信息,确保它是有效的并且没有过期。我输入了两次新密码。我已经知道我的电子邮件地址是什么,你已经知道我的电子邮件地址是什么,任何可能的黑客也会知道我的电子邮件是什么,所以不要让我输入它。让链接持续一整天太过分了。一个小时或更短的时间。
  • 我讨厌安全问题。别问我这个问题。基本上,这只是第二个故意降低安全性的密码,所以你会一直记住它。我没有经常飞行的英里数,我不知道我母亲的娘家姓等等。停下来。我知道这是为了阻止那些可能侵入你的电子邮件的陌生人,但是除非你是贝宝,我认为这只是工程。
  • 当您确认密码匹配并且可以接受时,请更新数据库(只存储我的密码的一个盐散列,而不是密码本身!)马上给我登录。不要将我重定向到登录页面,在那里我必须重新输入我已经给过你几次的信息(即使你已经知道是我,并且足够信任我来更改我自己的密码)。那太烦人了。用户不耐烦。
  • 我也不喜欢基于以下内容随机生成的密码:好的。

  • 通常我只是从邮件中复制粘贴密码。复制粘贴密码是您不希望用户做的事情。
  • 我必须手动更改密码,这意味着在用户控制面板或帐户设置或其他任何地方乱搞。我越来越不耐烦了!当我用一次性密码登录时,你可以用"更改密码"来加快速度,但这意味着增加了代码复杂性。现在您需要为此添加一个标志,添加另一个重定向,处理用户在输入新密码时超时的情况,等等。
  • 因为我只是人类,人类有多动症,我通常忘记做以上的事情,最后我得到了一个垃圾密码,我必须在下次登录时从我的电子邮件中找到并复制。我的错,但我还是要怪你的网站。;-)
  • 随机生成的密码解决方案也意味着,当基于链接的身份验证在可用性和安全性方面似乎是未来(OpenID等)时,您将始终使用基于密码的解决方案(我不想让100个小站点知道我的登录详细信息!).好的。

    更新以响应评论:好的。

    为什么哈希足够:如果一个黑客能猜出你生成的哈希的全部128+位(比如说一个小时内),那么他或她为什么不能猜出电子邮件呢?我知道询问电子邮件和/或安全问题"感觉"更安全,但是如果你考虑一下,电子邮件通常是非常可预测和统一的,熵率很低。我怀疑它们能被认为包含超过50位的信息。(可能要少得多)我敢打赌,我猜你的电子邮件比我猜一个50位的随机整数还快。但如果这是一个真正的担忧,你所需要做的就是在散列中添加更多的位。对于过杀模式——SHA256(salt, email, old pw hash, time stamp, maybe some bytes from /dev/urandom)或类似模式,应该是256位左右。如果一个黑客能预测到这一点,那么你真的做不了什么。很明显,他可以控制矩阵,如果他愿意的话,他可以把他的思想投射到硬盘里的磁性盘片上。好的。

    仍然支持openid:我访问的任何一个新网站,如果我要求创建一个用户,那么他们为什么想知道我的(一次性)密码,以及他们在安全方面为我提供的,openid或google/facebook/etc.不信任我的(一次性)密码,或者他们为什么不信任google/facebook/etc.没有人(我知道)会记住30个不同的密码。通常人们会重用它们,所以如果这些第三方网站创建者想这样做,那么他们就很容易欺骗他们的用户。如果我在你的网站注册了我通常的信息,你可以立即接管我的last.fm和reddit帐户,如果你愿意的话,还有可能十几个网站,我已经用了几次,忘记了。事实上,在当今时代,我有点期望站点如果想要他们严格不需要的细节,要么无知,要么有恶意意图,所以这就是我称之为一次性密码的原因——每次注册时,我都会说"这里,有我的reddit帐户,它和我将用于您的站点的L/P相同(否则我会忘记)。很好,我并不是特别喜欢它。"当然,如果他们愿意的话,谷歌可以接管我在线上的一切,但现在我会比你更信任谷歌(没有冒犯之意!).好的。好啊.


    首先,我建议您将密码重置视为安全的业务事务。并且单个请求独立于同一帐户的其他请求。生成一个随机的、不可重用的事务ID,并将其与此密码重置请求关联。然后,在您发送给他们的电子邮件中,使用URL嵌入事务ID:

    http://www.yoursite.com/passwordreset/?id=e3dXY81fr98c6v1

    这个所谓的密码重置事务应该与帐户相关联,并将元数据与密码重置相关联,例如请求日期和到期日期。帐户本身应该只知道有/有与之相关联的挂起的密码重置。

    另外,当用户要求重置密码时,忘记这个秘密问题——向他们发送一封您应该已经存档的电子邮件要安全得多。(如果没有,那么就开始收集它们!)-更好的是,使用他们的电子邮件地址作为用户名。

    当用户从该事务ID URL输入新密码时,您会相信它是您认为的人。为了确保这一点,您可以简单地要求他们重新输入他们的用户名(您已经确认了这一点)。


    Q1。嗯,有一个缺陷。为什么要求用户输入新密码?我宁愿生成一个新的随机密码并发送给他。收到密码后,用户可以使用随机生成的密码登录,然后在其配置文件中更改密码。

    我建议在大多数网站上使用以下系统:

  • 用户在"密码重置"窗体中输入邮件地址。
  • 邮件已验证(即数据库中是否有具有此邮件地址的用户?)
  • 新密码是随机生成并通过邮件发送的,然后进行盐渍/散列并保存到数据库中。
  • 用户登录。
  • 这很容易,也很常见,所以用户不会丢失。

    现在,您可以通过以下方式提高安全性(减少滥用):

    • 设置密码重置比率。一旦提交了表单,就会记住IP地址和提交的数据:现在,在几分钟内,来自同一IP地址的任何人都不能再重置密码。
    • 新生成的密码不能替换旧密码:相反,两者都可以使用。假设有人重置了另一个用户的密码。如果该用户没有阅读或收到带有新密码的邮件,则该用户必须仍然能够使用旧密码登录。

    顺便说一句,但这只是我个人的意见,除非需要,否则不要提供秘密的问答功能。我有太多的痛苦记得我在哪里回答了什么,所以我可能比密码更容易忘记答案。