63

应用程序发送电子邮件以验证用户帐户或重置密码。我相信以下是它应该的方式,我要求参考和实现。

如果一个应用程序必须在电子邮件中发送一个链接来验证用户的地址,在我看来,链接和应用程序对链接的处理应该具有以下特征:

  1. 该链接在请求 URI ( )中包含一个随机数。http://host/path?nonce
  2. 在点击链接 (GET) 时,用户会看到一个表单,可以选择使用 nonce。
  3. 用户确认输入(POST)。
  4. 服务器收到请求并
  • 检查输入参数,
  • 执行更改,
  • 并使随机数无效。

根据关于 Safe and Idempotent Methods 的 HTTP RFC,这应该是正确的。

问题是这个过程涉及一个额外的页面或用户操作(第 3 项),这被很多人认为是多余的(如果不是无用的话)。我在向同行和客户展示这种方法时遇到了问题,因此我要求更广泛的技术团队对此提供意见。我反对跳过 POST 步骤的唯一理由是可能从浏览器中预加载链接。

  • 是否有关于这个主题的参考资料可以更好地解释这个想法并说服非技术人员(来自期刊、博客等的最佳实践)?
  • 是否有实施这种方法的参考网站(最好是流行的和有很多用户的)?
  • 如果没有,是否有记录的原因或等效的替代方案?

谢谢你,
卡里姆


细节不遗余力

我保持了主要部分的简短,但是为了减少对我故意遗漏的细节的过多讨论,我将添加一些假设:

  • 电子邮件的内容不是本次讨论的一部分。用户知道她必须单击链接才能执行操作。如果用户没有反应,什么都不会发生,这也是众所周知的。
  • 我们不必说明我们向用户发送邮件的原因,也不必说明通信政策。我们假设用户希望收到电子邮件。
  • nonce 具有过期时间戳,并直接与收件人电子邮件地址相关联以减少重复。

笔记

使用 OpenID 等,普通的 Web 应用程序无需执行标准的用户帐户管理(密码、电子邮件...),但仍有一些客户想要“他们自己的用户

奇怪的是,我还没有在这里找到令人满意的问题或答案。到目前为止我发现了什么:

4

3 回答 3

27

这个问题与在 ASP.NET (C#) 中实现安全、唯一的“一次性”激活 URL非常相似。

我的答案与您的方案很接近,并指出了一些问题-例如有效期短,处理双重注册等。
您使用加密随机数也很重要,许多人倾向于跳过-例如“让我们使用 GUID"...

你提出的一个新观点,在这里很重要,就是 GET 的幂等性。
虽然我同意你的一般意图,但很明显,幂等性与一次性链接直接矛盾,这在某些情况下是必要的,例如这种情况。

我想假设这并没有真正违反 GET 的幂等性,但不幸的是它确实......另一方面,RFC 说 GET应该是幂等的,它不是必须的。所以我会说在这种情况下放弃它,并坚持一次性自动失效的链接。

如果您真的想严格遵守 RFC,而不是陷入非幂等(?) GET,您可以让 GET 页面自动提交 POST - 这是围绕 RFC 的那一点的漏洞,但合法,并且您不需要用户双重选择,而且您不会打扰他...

您真的不必担心预加载(您是在谈论 CSRF,还是浏览器优化器?)... CSRF 是无用的,因为随机数,优化器通常不会在预加载页面上处理 javascript(用于自动提交)。

于 2009-07-01T09:22:12.417 回答
9

关于密码重置:

通过向用户注册的电子邮件地址发送电子邮件来执行此操作的做法虽然在实践中很常见,但安全性并不好。这样做会将您的应用程序安全性完全外包给用户的电子邮件提供商。您需要多长时间的密码以及您使用的任何巧妙的密码散列都无关紧要。我将能够通过阅读发送给用户的电子邮件进入您的网站,因为我可以访问电子邮件帐户或者能够在发送给用户的任何地方阅读未加密的电子邮件(想想:邪恶的系统管理员)。

根据相关站点的安全要求,这可能重要也可能不重要,但作为该站点的用户,我至少希望能够禁用此类密码重置功能,因为我认为它不安全。

我找到了讨论该主题的白皮书。

如何以安全的方式执行此操作的简短版本:

  1. 要求提供有关帐户的确凿事实

    1. 用户名。
    2. 电子邮件地址。
    3. 10 位数的帐号或其他信息,例如社会保险号。
  2. 要求用户至少回答三个不可小觑的预定义问题(由您预定义,不要让用户创建自己的问题)。比如“你最喜欢的度假胜地是什么”,而不是“你最喜欢的颜色是什么”。

  3. 可选:向用户必须输入的预定义电子邮件地址或手机号码 (SMS) 发送确认码。

  4. 允许用户输入新密码。

于 2009-07-16T16:26:02.853 回答
1

我一般同意你的一些修改建议如下。

  1. 用户在您的网站上注册并提供电子邮件。
  2. 验证电子邮件通过两个链接发送到用户帐户:a) 一个带有 GUID 的链接,用于验证注册 b) 一个带有 GUID 的链接,用于拒绝验证
  3. 当他们通过电子邮件访问验证 URL 时,他们会自动进行验证,并且验证 guid 在您的系统中会被标记为此类。
  4. 当他们从他们的电子邮件中访问拒绝 URL 时,他们会自动从可能的验证队列中删除,但更重要的是,您可以告诉用户您对电子邮件注册感到抱歉,并为他们提供更多选项,例如从您的系统中删除他们的电子邮件。这将停止任何关于有人在您的系统中输入我的电子邮件的自定义服务类型投诉......等等等等。

是的,您应该假设当他们单击验证链接时,他们已通过验证。让他们单击页面中的第二个按钮有点多,并且仅在您计划向注册的人发送垃圾邮件的情况下进行双重选择样式注册时才需要。标准注册/验证方案通常不需要这个。

于 2009-06-30T23:50:12.130 回答