验证电子邮件应包含哪些内容?

信息安全 验证 电子邮件
2021-08-30 08:01:21

现在我正在生成一个存储在数据库中的 25 个字符的字符串,该字符串只能使用 1 次,并在用户注册后 30 分钟过期。

http://example.com/security/activate/ZheGgUNUFAbui4QJ48Ubs9Epd

我做了一个快速的数据库查找,逻辑如下:

如果帐户未激活并且电子邮件未验证并且验证码仍然有效,请激活帐户,将电子邮件地址标记为已验证并将验证码标记为已使用。

例如,它每 72 小时刷新一次过期和使用的验证码。这是为了告诉用户单击的激活链接已过期,例如,如果他在第二天查看他的电子邮件并尝试该链接。

我应该在 url 中包含用户 UUID 吗?我需要包含其他内容吗?

我考虑过在按下激活链接时确保注册表单上的 IP 地址与请求的 IP 地址匹配,但对我来说,我主要在手机上阅读我的电子邮件以获取此类内容,所以这对 UX 来说会很痛苦.

4个回答

您如何生成包含在 URL 中的 25 个字符的字符串?它是完全随机的,还是基于当前时间或用户电子邮件?它应该是随机的,不可猜测的。

您应该确保验证页面实际呈现(不仅仅是发生了 GET 请求)。诸如 chrome(和防病毒程序)之类的浏览器通常会加载 URL,而无需用户明确单击它们作为预取或出于安全原因进行扫描。

这可能会导致恶意行为者 (Eve) 想要使用其他人的电子邮件 (Alice) 创建帐户的情况。Eve 注册了,Alice 收到了一封电子邮件。爱丽丝打开了这封电子邮件,因为她对一个她没有请求的帐户感到好奇。她的浏览器(或防病毒软件)在后台请求 URL,无意中激活了帐户。

我会在页面上使用 JavaScript 来验证实际呈现的页面,并在电子邮件中包含一个链接,用户可以在其中报告他们没有创建此帐户。

添加到大雪的答案(因为我还不能写评论)。

创建一个表单并要求用户创建密码也不错。这样,用户需要输入新密码,提交后,帐户将被激活。它将解决后台防病毒检查。

至于URL,它应该足够长,因为它是随机字符串。您一次拥有 2 个相同内容的密钥的可能性很小。

检查 IP 并不好,因为某些 ISP 可能会轮换 IP 地址,因此您会阻止想要注册但不能注册的人。

您的电子邮件应包含激活码,而不是链接。您不应在电子邮件中发送任何用于帐户管理的链接。如果您(合法方)向用户发送电子邮件链接(尤其是带有长串随机字符),那么您就很难将合法电子邮件与网络钓鱼尝试区分开来。

激活码应包含易于复制和粘贴的字符(无空格、“+”、“-”等),并且也易于手动输入。字母和数字有效。激活码的安全性取决于它的不可预测性。您可以使用系统的安全随机数生成器导出该值,就像您应该使用 cookie 的会话 ID 一样。

激活码应存储在数据库表中,每一行都有一个配置文件 ID、激活码*和过期时间。您不想将配置文件 ID 或过期时间放在 cookie、URL 或激活码中。**恶意用户可能会篡改 ID 以接管另一个帐户。您需要在服务器端验证这些内容,因为您的安全策略不能盲目信任客户端数据。

激活码应通过 POST 请求提交。https://example.com/security/activate完成其余注册后,自动将用户重定向到帐户激活 URL(可以是)。使再次访问帐户激活页面变得容易,以防他们意外关闭它。

您不希望 GET 请求执行任何操作。链接可能会在没有用户交互的情况下被访问(由于浏览器预取或电子邮件安全服务)。此外,将机密信息放入 URL 可能会泄露敏感数据。(通过推荐标头或浏览器插件。)

不用担心IP,它仍然可能会改变。(与用户代理相同。)

我不知道取消功能是否可取。我什至不使用未经请求的电子邮件中的取消订阅链接,因为它可能是一种确定是否有人与电子邮件地址相关联的方法。如果激活码足够长以抵抗蛮力,或者如果您限制了激活码尝试的次数,那么我认为让激活码最终过期并没有什么害处。

另一方面,减少不需要的帐户激活电子邮件的数量可能会很好。为了礼貌起见,您可以限制发送到某个地址的电子邮件数量。说每天最多 3 次,每月最多 5 次。(我不知道这是否太高或太低。)作为非用户,我只会将您网站上的电子邮件自动删除或自动标记为已读。

对于不需要的激活电子邮件,需要考虑很多变量。很可能与用户体验有关,而不是安全性。您甚至可以提供“取消我的激活并且永远不会向该地址发送电子邮件,因为我永远不会注册”功能,但这有明显的问题。(您仍然需要验证此人的电子邮件。)

* 散列激活码并没有什么坏处。与密码一样,散列也不重要,因为每个代码都有一次使用,不包含私人信息,由服务器随机生成,并且会过期。

** 您实际上可以使用加密 MAC 防止篡改,但我强烈反对大多数开发人员尝试这样做。密码学很难正确。

与您使用安全实践的任何地方一样,暴露和威胁评估是您必须针对您的独特环境和用例进行评估的东西。现有的答案为评估提供了大量的接触点,以及要避免的事情的指针 - 例如GET触发的操作。相反,我将更多地关注 UX 的“用户”部分。我也会谈到散布在页面上的许多评论。

您通过电子邮件触发的操作“验证”的确切内容也是要考虑的一个因素。如果您所做的只是确认它是一个有效的电子邮件地址,那么几乎任何操作都足够了。验证电子邮件、创建帐户的意图以及接收电子邮件的用户是发起帐户创建的用户需要更多的努力。

但是,您不应该采取的一项“努力”是发送提醒电子邮件。假设用户有意创建了帐户,使用了有效的电子邮件地址,并希望将该帐户用于您提供帐户的任何目的,他们将寻找该电子邮件,并将尽快进行激活过程。如果他们在等待电子邮件时在其他问题上偏离了方向,链接、代码或其他任何内容可能会在他们使用之前过期。在这种情况下允许他们重新发送验证电子邮件是可以的。然而,提醒电子邮件更可能是垃圾邮件触发器,而不是对用户的好处。

作为用户,我很高兴有可用的选项来激活/验证我的帐户。我遇到的最常见的选项集是电子邮件提供了一个可以单击或剪切和粘贴的链接,以及我可以在网站上我的帐户设置区域内的页面上的表单字段中输入的确认代码。确认码很少是整数,长度为 5 到 9 位。

作为用户,我最有信心的验证电子邮件是那些在 URL 中具有加密哈希值的电子邮件(/verify?l=lgGS2SBjMTU4NjkwNjYxMjI5MDBhZDk2YjEyMzMzYjNhZmQxOb),这会将我带到一个对我来说独一无二的页面,然后我必须输入用于创建帐户的密码。哈希的使用确认链接是在电子邮件中收到的,没有被猜测或暴力破解,从而验证电子邮件是有效的。在任何其他操作之前,该唯一页面的服务允许服务器将其发送到的电子邮件标记为“有效”,而无需确认帐户创建。输入密码确认另一端有参与者,而不是某些防病毒、恶意软件检测或预取操作。密码的有效性以合理的确定性确认电子邮件的接收者和帐户的创建者是同一个人。

建议的 30 分钟时间限制似乎有点严格,而如果您的威胁评估表明您在 24 小时内的暴露是不可接受的,那么 24 小时的时间可能会太大。我相信 2 小时应该足以满足几乎所有用户的环境。如果可以重新发送验证,尤其如此。即使使用 14 kb/s 连接到远程 POP 帐户的移动设备也应该能够在 120 分钟内完成交换。

使用 JS 以某种方式验证人类行为可能会出现问题。JS 可以关闭,这比许多 Web 开发人员想知道的要频繁得多。其次,即使在浏览器中启用了 JS ,广告拦截器也可以在每个站点或每个源的基础上阻止 JS。我在全球范围内阻止了许多 JS 源,包括 Google 的分析脚本,并将一些用于站点的白名单,例如 Stack Exchange,我愿意支持它们使用我的数据。

在电子邮件或确认页面上包含一个链接来“取消”帐户是一种浪费。在电子邮件中,实际上会适得其反,因为这表明单击有关您不想要的帐户的链接是个好主意。取而代之的是,电子邮件应包含措辞,以表明无所作为将导致帐户无法确认,甚至可能被删除。确认页面上的取消链接更糟糕,因为它奖励了不良行为。我经常收到电子邮件,作为旧的 Google 混乱的一部分,被定向到另一个 Gmail 帐户,我认为另一个帐户也是如此。【以前google没有合并带点和不带点的用户名,所以我带点的用户名和别人的不带点的版本是不同的账号,

您将“已验证”电子邮件地址与激活链接结合的紧密程度取决于您的用例和威胁评估。当我在更改关联的电子邮件地址后必须重新验证我的帐户时,我有点恼火。我对流程的接受程度与我对账户的“价值”成正比。对于我的银行账户、PayPal 等,我 100% 接受。然而,在 PcPartsPicker 上,我大约有 15% 的人会接受这样的过程。

至于 IP 和/或用户代理,请忽略它们。例如,我经常会查看网站,并选择使用我的移动设备创建一个帐户。但是,我不会在上面打开电子邮件。如果我创建了一个帐户,并得知我需要以某种方式验证或确认它,并且电子邮件是提供的方法,我会等到我回到家在我的桌面上打开电子邮件,在那里我可以检查它。因此,IP 和用户代理将非常不同。但是,我的密码将保持不变,这足以证明我是原始帐户创建者。

请记住,电子邮件与时代广场的 Jumbo-tron 一样安全,然后相应地进行操作。