5522

版主备注:

这个问题不适合我们的问答格式以及当前适用于 Stack Overflow的话题性规则。对于内容仍然有价值的此类问题,我们通常使用“历史锁定”。但是,此问题的答案得到积极维护,历史锁定不允许编辑答案。因此,已应用“wiki 答案”锁定以允许编辑答案。您应该假设存在通常由历史锁定处理的话题性问题(即这个问题不是 Stack Overflow 的话题性问题的一个很好的例子)。

网站基于表单的身份验证

我们认为 Stack Overflow 不应该只是针对非常具体的技术问题的资源,还应该提供有关如何解决常见问题变体的一般指南。“基于表单的网站身份验证”应该是此类实验的一个很好的主题。

它应包括以下主题:

  • 如何登录
  • 如何退出
  • 如何保持登录状态
  • 管理 cookie(包括推荐设置)
  • SSL/HTTPS 加密
  • 如何存储密码
  • 使用秘密问题
  • 忘记用户名/密码功能
  • 使用nonce防止跨站点请求伪造 (CSRF)
  • 开放ID
  • “记住我”复选框
  • 浏览器自动完成用户名和密码
  • 秘密 URL(受摘要保护的公共URL )
  • 检查密码强度
  • 电子邮件验证
  • 以及更多关于 基于表单的身份验证...

它不应包括以下内容:

  • 角色和授权
  • HTTP 基本认证

请通过以下方式帮助我们:

  1. 建议子主题
  2. 提交关于这个主题的好文章
  3. 编辑官方答案
4

11 回答 11

3903

第一部分:如何登录

我们假设您已经知道如何构建一个登录+密码 HTML 表单,该表单将值 POST 到服务器端的脚本以进行身份​​验证。以下部分将讨论可靠实用的身份验证模式,以及如何避免最常见的安全陷阱。

使用 HTTPS 还是不使用 HTTPS?

除非连接已经是安全的(即,使用 SSL/TLS 通过 HTTPS 进行隧道连接),否则您的登录表单值将以明文形式发送,这样任何人在浏览器和 Web 服务器之间的线路上窃听都可以在登录时读取它们通过通过。这种类型的窃听通常由政府进行,但一般来说,我们不会处理“拥有”的电线,而是说:只需使用 HTTPS。

本质上,在登录期间防止窃听/数据包嗅探的唯一实用方法是使用 HTTPS 或其他基于证书的加密方案(例如TLS)或经过验证和测试的质询-响应方案(例如Diffie-Hellman基于 SRP)。窃听攻击者可以轻松绕过任何其他方法。

当然,如果您愿意有点不切实际,您也可以采用某种形式的双因素身份验证方案(例如 Google Authenticator 应用程序、物理“冷战式”密码本或 RSA 密钥生成器加密狗)。如果应用得当,这甚至可以在不安全的连接下工作,但很难想象开发人员愿意实现双因素身份验证而不是 SSL。

(不要)滚动你自己的 JavaScript 加密/散列

考虑到在您的网站上设置 SSL 证书的成本和技术难度(尽管现在可以避免),一些开发人员很想推出自己的浏览器内散列或加密方案,以避免通过不安全的线路传递明文登录。

虽然这是一个崇高的想法,但它本质上是无用的(并且可能是一个安全漏洞),除非它与上述之一相结合 - 也就是说,要么使用强加密来保护线路,要么使用久经考验的挑战 - 响应机制(如果你不知道那是什么,只知道它是数字安全中最难证明、最难设计和最难实现的概念之一)。

虽然散列密码确实可以有效防止密码泄露,但它很容易受到重放攻击、中间人攻击/劫持(如果攻击者可以在不安全的 HTML 页面到达您的浏览器,他们可以简单地注释掉 JavaScript 中的散列)或暴力攻击(因为您将用户名、盐和散列密码都交给了攻击者)。

反人类的验证码

CAPTCHA旨在阻止一种特定类型的攻击:无需人工操作的自动字典/蛮力试错法。毫无疑问,这是一个真正的威胁,但是,有一些方法可以无缝地处理它,不需要验证码,专门设计的服务器端登录限制方案——我们稍后会讨论这些。

知道 CAPTCHA 实现的创建方式不同;它们通常不是人类可以解决的,它们中的大多数实际上对机器人无效,它们都对廉价的第三世界劳动力无效(根据OWASP,目前的血汗工厂费率为每 500 次测试 12 美元),并且一些实现可能是在某些国家/地区在技术上是非法的(请参阅OWASP 身份验证备忘单)。如果您必须使用 CAPTCHA,请使用 Google 的reCAPTCHA,因为根据定义,它是 OCR 难的(因为它使用了已经 OCR 错误分类的图书扫描)并且非常努力地使用户友好。

就我个人而言,我倾向于发现 CAPTCHAS 很烦人,并且仅在用户多次登录失败并且限制延迟被最大化时才使用它们作为最后的手段。这种情况很少会发生,以至于无法接受,它会加强整个系统。

存储密码/验证登录

在我们近年来看到的所有高度公开的黑客攻击和用户数据泄漏之后,这可能最终成为常识,但必须说:不要在数据库中以明文形式存储密码。用户数据库通常会通过 SQL 注入被黑客入侵、泄露或收集,如果您存储的是原始的明文密码,那么为了您的登录安全,这就是即时游戏结束。

因此,如果您无法存储密码,如何检查从登录表单发布的登录名+密码组合是否正确?答案是使用密钥派生函数进行散列。每当创建新用户或更改密码时,您都会获取密码并通过 KDF 运行它,例如 Argon2、bcrypt、scrypt 或 PBKDF2,将明文密码(“correcthorsebatterystaple”)变成一个长的、看起来随机的字符串,存储在数据库中要安全得多。要验证登录,您对输入的密码运行相同的哈希函数,这次传入盐并将生成的哈希字符串与存储在数据库中的值进行比较。Argon2、bcrypt 和 scrypt 已经用哈希值存储了盐。查看 sec.stackexchange 上的这篇文章以获取更多详细信息。

使用盐的原因是散列本身是不够的——你需要添加一个所谓的“盐”来保护散列不受彩虹表的影响。盐可以有效地防止两个完全匹配的密码被存储为相同的哈希值,如果攻击者正在执行密码猜测攻击,可以防止一次扫描整个数据库。

密码散列不应该用于密码存储,因为用户选择的密码不够强大(即通常不包含足够的熵),并且可以通过访问散列的攻击者在相对较短的时间内完成密码猜测攻击。这就是使用 KDF 的原因 - 这些有效地“拉伸密钥”,这意味着攻击者每次猜测密码都会导致哈希算法重复多次,例如 10,000 次,这导致攻击者猜测密码的速度要慢 10,000 倍。

会话数据 - “您以 Spiderman69 身份登录”

一旦服务器根据您的用户数据库验证了登录名和密码并找到匹配项,系统需要一种方法来记住浏览器已经过身份验证。这个事实应该只存储在服务器端的会话数据中。

如果您不熟悉会话数据,以下是它的工作原理:一个随机生成的字符串存储在即将到期的 cookie 中,并用于引用存储在服务器上的数据集合 - 会话数据。如果您使用的是 MVC 框架,那么这无疑已经处理好了。

如果可能,请确保会话 cookie 在发送到浏览器时设置了安全和仅 HTTP 标志。HttpOnly 标志对通过 XSS 攻击读取的 cookie 提供了一些保护。安全标志确保 cookie 仅通过 HTTPS 发送回来,因此可以防止网络嗅探攻击。cookie 的值不应是可预测的。在出现引用不存在会话的 cookie 时,应立即替换其值以防止会话固定

会话状态也可以在客户端维护。这是通过使用 JWT(JSON Web 令牌)等技术实现的。

第二部分:如何保持登录状态——臭名昭著的“记住我”复选框

持久登录 Cookie(“记住我”功能)是一个危险区域;一方面,当用户了解如何处理它们时,它们完全与传统登录一样安全;另一方面,对于粗心的用户来说,它们是一个巨大的安全风险,他们可能会在公共计算机上使用它们而忘记注销,并且可能不知道浏览器 cookie 是什么或如何删除它们。

就个人而言,我喜欢对我定期访问的网站进行持久登录,但我知道如何安全地处理它们。如果您确信您的用户知道相同的内容,您可以使用无愧于心的持久登录。如果不是 - 好吧,那么您可能会同意这样一种哲学,即粗心的用户登录凭据如果被黑客入侵,就会自找麻烦。我们也不会去用户家中撕下所有那些用他们在显示器边缘排列的密码的便签纸。

当然,有些系统承受不起任何帐户被黑的后果;对于此类系统,您无法证明拥有持久登录是合理的。

如果您决定实施持久登录 cookie,您可以这样做:

  1. 首先,花点时间阅读Paragon Initiative关于该主题的文章。您需要正确掌握一堆元素,并且这篇文章很好地解释了每个元素。

  2. 重申一下最常见的陷阱之一,不要将持久登录 COOKIE(令牌)存储在您的数据库中,只存储它的哈希值!登录令牌是密码等效的,因此如果攻击者掌握了您的数据库,他们可以使用令牌登录到任何帐户,就像它们是明文登录密码组合一样。因此,在存储持久登录令牌时,使用散列(根据https://security.stackexchange.com/a/63438/5002,弱散列可以很好地实现此目的)。

第三部分:使用秘密问题

不要实施“秘密问题”。“秘密问题”功能是一种安全反模式。从必读列表中的链接号 4 中阅读论文。你可以问莎拉佩林关于那个,在她的雅虎之后!电子邮件帐户在之前的总统竞选期间被黑了,因为她的安全问题的答案是……“瓦西拉高中”!

即使有用户指定的问题,大多数用户也很可能会选择:

  • 一个“标准”的秘密问题,比如母亲的娘家姓或最喜欢的宠物

  • 任何人都可以从他们的博客、LinkedIn 个人资料或类似内容中提取的一个简单的琐事

  • 任何比猜密码更容易回答的问题。对于任何体面的密码,这是您可以想象的每一个问题

总之,安全问题在几乎所有形式和变体中本质上都是不安全的,并且不应该出于任何原因在身份验证方案中使用。

安全问题在野外存在的真正原因是,它们方便地节省了一些无法访问其电子邮件以获取重新激活代码的用户的支持电话的成本。这是以牺牲安全和莎拉佩林的声誉为代价的。值得?可能不是。

第 IV 部分:忘记密码功能

我已经提到了为什么你不应该使用安全问题来处理忘记/丢失的用户密码;不言而喻,您永远不应该通过电子邮件向用户发送他们的实际密码。在这个领域至少还有两个非常常见的陷阱需要避免:

  1. 不要将忘记的密码重置为自动生成的强密码 - 众所周知,这样的密码很难记住,这意味着用户必须更改或写下来 - 例如,在显示器边缘的亮黄色便利贴上。与其设置新密码,不如让用户立即选择一个新密码——这就是他们想要做的事情。(如果用户普遍使用密码管理器来存储/管理通常不写下来就无法记住的密码,则可能是一个例外)。

  2. 始终对数据库中丢失的密码代码/令牌进行哈希处理。再次,此代码是密码等效项的另一个示例,因此必须对其进行哈希处理,以防攻击者获得您的数据库。当请求丢失密码代码时,将明文代码发送到用户的电子邮件地址,然后对其进行哈希处理,将哈希值保存在您的数据库中 - 并丢弃原始. 就像密码或持久登录令牌一样。

最后一点:始终确保您输入“丢失的密码代码”的界面至少与您的登录表单本身一样安全,否则攻击者会简单地使用它来获取访问权限。确保生成很长的“丢失密码”(例如,16 个区分大小写的字母数字字符)是一个好的开始,但请考虑添加与登录表单本身相同的限制方案。

第五部分:检查密码强度

首先,您需要阅读这篇小文章进行现实检查:500 个最常见的密码

好的,所以也许该列表不是任何地方任何系统上最常见密码的规范列表,但它很好地表明了当没有实施强制策略时人们将如何选择他们的密码。此外,当您将其与对最近被盗密码的公开分析进行比较时,该列表看起来非常接近家常便饭。

所以:没有最低密码强度要求,2% 的用户使用前 20 个最常见的密码之一。含义:如果攻击者仅获得 20 次尝试,那么您网站上 50 个帐户中就有 1 个是可破解的。

阻止这一点需要计算密码的熵,然后应用阈值。美国国家标准与技术研究院 (NIST)特别出版物 800-63有一组非常好的建议。结合字典和键盘布局分析(例如,'qwertyuiop' 是一个错误的密码),可以拒绝 99%的 18 位熵级别的所有错误选择的密码。简单地计算密码强度并向用户显示视觉强度计是好的,但还不够。除非强制执行,否则很多用户很可能会忽略它。

对于高熵密码的用户友好性,强烈推荐Randall Munroe 的密码强度 xkcd 。

利用 Troy Hunt 的Have I Been Pwned API来检查用户密码与公共数据泄露中泄露的密码。

第 VI 部分:更多 - 或:防止快速登录尝试

首先,看一下数字:密码恢复速度 - 您的密码可以保存多长时间

如果您没有时间浏览该链接中的表格,以下是它们的列表:

  1. 破解一个弱密码几乎不需要时间,即使你是用算盘破解它

  2. 如果不区分大小写,则几乎不需要时间来破解字母数字 9 字符的密码

  3. 如果长度小于 8个字符(台式电脑一次最多可以搜索整个键空间 7 个字符),破解复杂的符号、字母和数字、大小写密码几乎不需要任何时间数天甚至数小时)

  4. 但是,如果您被限制为每秒尝试一次,即使是 6 个字符的密码也将花费大量时间!

那么我们可以从这些数字中学到什么?好吧,很多,但我们可以专注于最重要的部分:防止大量快速连续登录尝试(即暴力攻击)确实并不难。但预防它并不像看起来那么容易。

一般来说,您有三种选择都可以有效抵抗暴力攻击(和字典攻击,但由于您已经采用了强密码策略,因此它们不应该成为问题)

  • 在 N 次尝试失败后显示验证码(非常烦人,而且通常无效——但我在这里重复自己)

  • 在 N 次尝试失败后锁定帐户并要求电子邮件验证(这是等待发生的DoS攻击)

  • 最后,登录限制:也就是说,在 N 次尝试失败后设置尝试之间的时间延迟(是的,DoS 攻击仍然可能,但至少它们的可能性要小得多,而且实施起来要复杂得多)。

最佳实践#1:随着失败尝试次数的增加而增加的短时间延迟,例如:

  • 1 次尝试失败 = 无延迟
  • 2 次失败尝试 = 2 秒延迟
  • 3 次失败尝试 = 4 秒延迟
  • 4 次失败尝试 = 8 秒延迟
  • 5 次失败尝试 = 16 秒延迟
  • 等等

DoS 攻击这种方案是非常不切实际的,因为由此产生的锁定时间略大于先前锁定时间的总和。

澄清一下:延迟不是将响应返回给浏览器之前的延迟。它更像是一个超时或不应期,在此期间,对特定帐户或从特定 IP 地址的登录尝试根本不会被接受或评估。也就是说,正确的凭据不会在成功登录时返回,不正确的凭据不会触发延迟增加。

最佳实践 #2:中等长度的时间延迟,在 N 次尝试失败后生效,例如:

  • 1-4 次失败尝试 = 无延迟
  • 5 次失败尝试 = 15-30 分钟延迟

DoS 攻击这种方案是非常不切实际的,但肯定是可行的。此外,可能需要注意的是,如此长的延迟对于合法用户来说可能非常烦人。健忘的用户会不喜欢你。

最佳实践#3:结合这两种方法 - 在 N 次尝试失败后生效的固定、短时间延迟,例如:

  • 1-4 次失败尝试 = 无延迟
  • 5 次以上失败尝试 = 20 秒延迟

或者,具有固定上限的延迟增加,例如:

  • 1 次尝试失败 = 5 秒延迟
  • 2 次失败尝试 = 15 秒延迟
  • 3 次以上失败尝试 = 45 秒延迟

这个最终方案取自 OWASP 最佳实践建议(必读列表中的链接 1),并且应该被视为最佳实践,即使它被承认在限制方面。

但是,根据经验,我会说:您的密码策略越强,您就越不会因延迟而困扰用户。如果您需要强(区分大小写的字母数字 + 所需的数字和符号)9+ 个字符的密码,您可以在激活限制之前为用户提供 2-4 次非延迟密码尝试。

DoS 攻击这个最终的登录限制方案是非常不切实际的。最后一点,始终允许持久性 (cookie) 登录(和/或 CAPTCHA 验证的登录表单)通过,因此合法用户甚至不会在攻击进行时被延迟。这样,非常不切实际的 DoS 攻击就变成了非常不切实际的攻击。

此外,对管理员帐户进行更积极的限制是有意义的,因为这些是最有吸引力的入口点

第七部分:分布式蛮力攻击

顺便说一句,更高级的攻击者会尝试通过“传播他们的活动”来规避登录限制:

  • 在僵尸网络上分发尝试以防止 IP 地址标记

  • 他们不会选择一个用户并尝试 50.000 个最常见的密码(由于我们的限制,他们不能这样做),而是选择最常见的密码并尝试针对 50.000 个用户。这样,他们不仅可以绕过验证码和登录限制等最大尝试次数,而且成功的机会也会增加,因为最常见的 1 号密码比 49.995 号更有可能

  • 将每个用户帐户的登录请求间隔 30 秒,以便在雷达下潜行

在这里,最佳实践是记录系统范围内的失败登录次数,并使用站点的错误登录频率的运行平均值作为上限,然后对所有用户施加上限。

太抽象了?让我改写一下:

假设您的网站在过去 3 个月内平均每天有 120 次错误登录。使用它(运行平均值),您的系统可能会将全局限制设置为 3 倍——即。24 小时内 360 次失败的尝试。然后,如果在一天内所有帐户的失败尝试总数超过了该数字(或者甚至更好,监控加速率并在计算的阈值上触发),它会激活系统范围的登录限制——这意味着所有用户的短暂延迟(仍然,cookie 登录和/或备份 CAPTCHA 登录除外)。

我还发布了一个问题,其中包含更多详细信息以及关于如何避免棘手的陷阱以抵御分布式暴力攻击的非常好的讨论

第 VIII 部分:双因素身份验证和身份验证提供程序

凭据可能会受到破坏,无论是通过漏洞利用、密码被写下和丢失、带有密钥的笔记本电脑被盗,还是用户登录到钓鱼网站。登录可以通过双重身份验证得到进一步保护,该身份验证使用带外因素,例如从电话、SMS 消息、应用程序或加密狗收到的一次性代码。一些提供商提供双因素身份验证服务。

身份验证可以完全委托给单点登录服务,由另一个提供者处理收集凭据。这会将问题推给受信任的第三方。Google 和 Twitter 都提供基于标准的 SSO 服务,而 Facebook 提供类似的专有解决方案。

关于 Web 身份验证的必读链接

  1. OWASP 认证指南/ OWASP 认证备忘单
  2. Web 上客户端身份验证的注意事项(非常易读的 MIT 研究论文)
  3. 维基百科:HTTP cookie
  4. 后备认证的个人知识问题:Facebook时代的安全问题(非常可读的伯克利研究论文)
于 2009-01-25T11:27:46.093 回答
430

权威文章

发送凭据

100% 安全发送凭据的唯一实用方法是使用SSL。使用 JavaScript 对密码进行哈希处理是不安全的。客户端密码散列的常见缺陷:

  • 如果客户端和服务器之间的连接未加密,那么您所做的一切都容易受到中间人攻击。攻击者可以替换传入的 javascript 以破坏散列或将所有凭据发送到他们的服务器,他们可以监听客户端响应并完美地模拟用户等等。具有受信任证书颁发机构的 SSL 旨在防止中间人攻击。
  • 如果您不在服务器上执行额外的冗余工作,服务器收到的散列密码的安全性会降低。

还有另一种称为SRP的安全方法,但它已获得专利(尽管它是免费许可的),而且很少有好的实现可用。

存储密码

永远不要将密码作为明文存储在数据库中。即使您不关心自己网站的安全性,也不会。假设您的某些用户将重复使用其在线银行帐户的密码。因此,存储散列密码,并丢弃原始密码。并确保密码不会出现在访问日志或应用程序日志中。OWASP推荐使用 Argon2作为新应用的首选。如果这不可用,则应使用 PBKDF2 或 scrypt。最后,如果以上都不可用,请使用 bcrypt。

哈希本身也是不安全的。例如,相同的密码意味着相同的哈希——这使得哈希查找表成为一次破解大量密码的有效方法。相反,存储盐渍哈希。盐是在散列之前附加到密码的字符串 - 每个用户使用不同的(随机)盐。salt 是一个公共值,因此您可以将它们与哈希一起存储在数据库中。有关更多信息,请参见此处

这意味着您不能向用户发送他们忘记的密码(因为您只有哈希)。除非您对用户进行了身份验证,否则请勿重置用户的密码(用户必须证明他们能够阅读发送到存储(并经过验证)的电子邮件地址的电子邮件。)

安全问题

安全问题是不安全的 - 避免使用它们。为什么?安全问题所做的任何事情,密码都会做得更好。阅读第 III 部分:在@Jens Roland中使用秘密问题在此 wiki 中回答此处。

会话 cookie

用户登录后,服务器会向用户发送会话 cookie。服务器可以从 cookie 中检索用户名或 id,但没有其他人可以生成这样的 cookie(TODO 解释机制)。

Cookie 可以被劫持:它们仅与客户端机器的其余部分和其他通信一样安全。它们可以从磁盘读取,在网络流量中嗅探,通过跨站点脚本攻击解除,从中毒的 DNS 钓鱼,因此客户端将其 cookie 发送到错误的服务器。不要发送持久性 cookie。Cookie 应在客户端会话结束时过期(浏览器关闭或离开您的域)。

如果您想自动登录您的用户,您可以设置一个持久性 cookie,但它应该与完整会话 cookie 不同。您可以设置用户已自动登录的附加标志,并且需要真实登录以进行敏感操作。这在希望为您提供无缝、个性化购物体验但仍保护您的财务详细信息的购物网站中很受欢迎。例如,当您返回访问亚马逊时,他们会向您显示一个看起来您已登录的页面,但当您下订单(或更改您的送货地址、信用卡等)时,他们会要求您确认你的密码。

另一方面,银行和信用卡等金融网站只有敏感数据,不应允许自动登录或低安全模式。

外部资源清单

于 2008-08-02T20:40:45.533 回答
168

首先,强烈警告这个答案不是最适合这个确切的问题。它绝对不应该是最佳答案!

我将继续提及 Mozilla 提出的BrowserID(或者更准确地说,是Verified Email Protocol),本着为未来更好的身份验证方法寻找升级路径的精神。

我会这样总结:

  1. Mozilla 是一家非营利组织,其价值观与为这个问题找到好的解决方案非常吻合。
  2. 今天的现实是大多数网站都使用基于表单的身份验证
  3. 基于表单的身份验证有一个很大的缺点,那就是增加了网络钓鱼的风险。要求用户将敏感信息输入到由远程实体控制的区域,而不是由其用户代理(浏览器)控制的区域。
  4. 由于浏览器是隐式信任的(用户代理的整个想法是代表用户行事),它们可以帮助改善这种情况。
  5. 这里阻碍进展的主要力量是部署僵局。必须将解决方案分解为可以单独提供一些增量收益的步骤。
  6. 用于表达内置于互联网基础设施中的身份的最简单的去中心化方法是域名。
  7. 作为表达身份的第二层,每个域都管理自己的一组帐户。
  8. “帐户@域”形式简洁明了,并得到广泛的协议和 URI 方案的支持。当然,这样的标识符是最普遍认可的电子邮件地址。
  9. 电子邮件提供商已经是事实上的主要在线身份提供商。如果您可以证明您控制了该帐户的关联电子邮件地址,则当前的密码重置流程通常可以让您控制该帐户。
  10. 验证电子邮件协议旨在提供一种基于公钥加密的安全方法,用于简化向域 B 证明您在域 A 上拥有帐户的过程。
  11. 对于不支持验证电子邮件协议的浏览器(目前全部),Mozilla 提供了一个 shim,它在客户端 JavaScript 代码中实现该协议。
  12. 对于不支持验证电子邮件协议的电子邮件服务,该协议允许第三方充当受信任的中介,声称他们已经验证了用户对帐户的所有权。拥有大量此类第三方是不可取的;此功能仅用于允许升级路径,并且更希望电子邮件服务自己提供这些断言。
  13. Mozilla 提供自己的服务,以充当此类受信任的第三方。实施验证电子邮件协议的服务提供商(即依赖方)可以选择信任或不信任 Mozilla 的断言。Mozilla 的服务使用发送带有确认链接的电子邮件的传统方式来验证用户的帐户所有权。
  14. 除了他们可能希望提供的任何其他身份验证方法之外,服务提供商当然可以提供此协议作为选项。
  15. 这里寻求的一个很大的用户界面好处是“身份选择器”。当用户访问网站并选择进行身份验证时,他们的浏览器会向他们显示电子邮件地址的选择(“个人”、“工作”、“政治活动”等),他们可能会使用这些地址向该网站表明自己的身份。
  16. 作为这项工作的一部分,正在寻求的另一个重要的用户界面好处是帮助浏览器更多地了解用户的会话——他们目前主要以谁的身份登录——因此它可能会在浏览器 chrome 中显示。
  17. 由于该系统的分布式特性,它避免了锁定到 Facebook、Twitter、Google 等主要网站。任何个人都可以拥有自己的域,因此可以充当自己的身份提供者。

这并不是严格意义上的“基于表单的网站身份验证”。但这是从当前基于表单的身份验证规范过渡到更安全的东西的努力:浏览器支持的身份验证。

于 2011-08-08T15:32:34.210 回答
149

我只是想我会分享这个我发现工作得很好的解决方案。

我称之为虚拟场(虽然我没有发明这个所以不要相信我)。

简而言之:您只需将其插入您的<form>并在验证时检查它是否为空:

<input type="text" name="email" style="display:none" />

诀窍是欺骗机器人认为它必须将数据插入到必填字段中,这就是我将输入命名为“电子邮件”的原因。如果您已经有一个名为 email 的字段正在使用,您应该尝试将虚拟字段命名为其他名称,例如“company”、“phone”或“emailaddress”。只需选择您知道不需要的内容,以及听起来人们通常认为合乎逻辑的内容来填写网络表单。input现在使用 CSS 或 JavaScript/jQuery隐藏该字段 - 任何最适合您的 - 只是不要将输入设置typehidden,否则机器人不会上当。

当您验证表单(客户端或服务器端)时,请检查您的虚拟字段是否已填写,以确定它是由人类还是机器人发送的。

例子:

如果是人类: 用户将看不到虚拟字段(在我的情况下名为“电子邮件”)并且不会尝试填充它。因此,当表单已发送时,虚拟字段的值仍应为空。

在机器人的情况下:机器人将看到一个字段,其类型是text和名称email(或您所称的任何名称),并会在逻辑上尝试用适当的数据填充它。它不在乎你是否使用一些花哨的 CSS 来设置输入表单的样式,Web 开发人员一直都在这样做。无论 dummy 字段中的值是什么,只要它比0字符大,我们都不在乎。

我结合CAPTCHA在留言簿上使用了这种方法,从那以后我再也没有看到过任何垃圾邮件。我之前使用过仅限 CAPTCHA 的解决方案,但最终,它导致每小时大约有五个垃圾邮件帖子。在表单中添加虚拟字段已停止(至少到现在为止)所有垃圾邮件的出现。

我相信这也可以与登录/身份验证表单一起使用。

警告:当然,这种方法不是 100% 万无一失的。可以对机器人进行编程以忽略display:none应用了样式的输入字段。您还必须考虑使用某种形式的自动完成(就像大多数浏览器都内置了!)为他们自动填写所有表单字段的人。他们也可以选择一个虚拟字段。

您也可以通过使虚拟字段可见但在屏幕边界之外来稍微改变这一点,但这完全取决于您。

要有创意!

于 2012-05-22T12:11:20.310 回答
87

我不认为上面的答案是“错误的”,但是还有很多没有涉及到的身份验证领域(或者更确切地说,重点是“如何实现 cookie 会话”,而不是“哪些选项可用以及交易是什么-offs”。

我建议的编辑/答案是

  • 问题更多在于帐户设置而不是密码检查。
  • 使用双因素身份验证比更聪明的密码加密方式更安全
  • 不要尝试实现自己的登录表单或密码的数据库存储,除非存储的数据在创建帐户和自行生成时没有价值(即 Facebook、Flickr等 web 2.0 风格)

    1. 摘要身份验证是所有主要浏览器和服务器都支持的基于标准的方法,即使通过安全通道也不会发送密码。

这避免了任何需要“会话”或 cookie,因为浏览器本身每次都会重新加密通信。它是最“轻量级”的开发方式。

但是,我不建议这样做,除非是公共的、低价值的服务。这是上面其他一些答案的问题 - 不要尝试重新实现服务器端身份验证机制 - 这个问题已得到解决并得到大多数主要浏览器的支持。不要使用cookies。不要在您自己的手动数据库中存储任何内容。只需根据请求询问请求是否经过身份验证。其他一切都应该由配置和第三方受信任的软件支持。

所以 ...

首先,我们将最初创建帐户(使用密码)与随后重新检查密码混淆了。如果我是 Flickr 并且第一次创建您的网站,那么新用户可以访问零值(空白网络空间)。我真的不在乎创建帐户的人是否对他们的名字撒谎。如果我正在创建医院内联网/外联网的帐户,其价值在于所有医疗记录,因此我确实关心帐户创建者的身份 (*)。

这是非常非常困难的部分。唯一体面的解决方案是信任网络。例如,您以医生身份加入医院。你用你的照片、护照号码和公钥创建一个托管在某个地方的网页,然后用私钥对它们进行哈希处理。然后您访问医院,系统管理员查看您的护照,查看照片是否与您匹配,然后使用医院私钥对网页/照片哈希进行哈希处理。从现在开始,我们可以安全地交换密钥和令牌。任何信任医院的人都可以(顺便说一句,这里有秘诀)。系统管理员还可以为您提供RSA加密狗或其他双重身份验证。

但这很麻烦,而且不是 web 2.0。但是,这是创建新帐户的唯一安全方法,这些帐户可以访问非自行创建的有价值信息。

  1. Kerberos 和 SPNEGO - 具有可信第三方的单点登录机制 - 基本上,用户针对可信第三方进行验证。(注意,这绝不是不可信的OAuth

  2. SRP - 一种没有受信任第三方的巧妙密码认证。但是在这里,我们进入了“使用两因素身份验证更安全,即使这更昂贵”的领域

  3. SSL客户端——给客户端一个公钥证书(在所有主流浏览器中都支持——但对客户端机器的安全性提出了质疑)。

最后,这是一个权衡 - 安全漏洞的成本与实施更安全方法的成本是多少。有一天,我们可能会看到一种适当的PKI被广泛接受,因此不再拥有自己的滚动身份验证表单和数据库。一天...

于 2011-08-08T16:29:10.103 回答
59

散列时,不要使用 MD5 等快速散列算法(存在许多硬件实现)。使用类似 SHA-512 的东西。对于密码,较慢的哈希值更好。

创建散列的速度越快,任何蛮力检查器的工作速度就越快。因此,较慢的哈希将减慢暴力破解。对于较长的密码(8 位 +),慢速哈希算法将使暴力破解变得不切实际

于 2011-08-08T23:07:08.973 回答
56

关于身份验证系统,我最喜欢的规则是:使用密码,而不是密码。容易记住,很难破解。更多信息:编码恐怖:密码与密码短语

于 2012-11-24T21:15:52.187 回答
32

我想添加一个我使用过的建议,基于深度防御。您不需要为管理员使用与普通用户相同的身份验证和身份验证系统。您可以在单独的 url 上有一个单独的登录表单,为将授予高权限的请求执行单独的代码。这个可以做出对普通用户来说完全是痛苦的选择。我使用的一种方法是实际打乱登录 URL 以供管理员访问,并通过电子邮件向管理员发送新 URL。立即停止任何蛮力攻击,因为您的新 URL 可能非常困难(非常长的随机字符串),但您的管理员用户唯一的不便之处是关注他们电子邮件中的链接。攻击者甚至不知道在哪里发布。

于 2015-07-18T01:18:52.113 回答
21

我不知道最好将其作为答案还是作为评论来回答。我选择了第一个选项。

关于第一个答案中的第四部分:忘记密码功能,我想说明一下时间攻击。

记住您的密码表单中,攻击者可能会检查完整的电子邮件列表并检测哪些已注册到系统(请参见下面的链接)。

关于忘记密码表单,我要补充一点,使用一些延迟功能来相等的成功和不成功查询之间的时间是一个好主意。

https://crypto.stanford.edu/~dabo/papers/webtiming.pdf

于 2015-08-16T17:31:35.713 回答
19

我想补充一条非常重要的评论:-

  • “在公司的 内部网环境中”,如果不是全部,上述大部分内容可能都不适用!

许多公司部署“仅供内部使用”的网站,这些网站实际上是恰好通过 URL 实现的“公司应用程序”。这些 URL 可以(据说......)只能在“公司的内部网络”中解析。(哪个网络神奇地包括所有连接 VPN 的“公路勇士”。)

当用户尽职地连接到上述网络时,他们的身份(“身份验证”) [已经......]“确凿地知道”,因为他们允许(“授权”)做某些事情......例如。 ..“访问这个网站。”

这种“身份验证+授权”服务可以由几种不同的技术提供,例如 LDAP (Microsoft OpenDirectory)或 Kerberos。

从您的角度来看,您只知道这一点:任何合法地在您的网站上结束的人都必须伴随着 [一个神奇地包含...的环境变量] 一个“令牌”。(没有这样的标记必须是直接的理由404 Not Found。)

令牌的价值对您来说没有意义,但是,如果需要,“存在适当的方法”,您的网站可以“[权威地]询问知道(LDAP ...等)的人”任何和所有(!)你可能有的问题。换句话说,你没有利用任何“本土逻辑”。相反,你询问管理局并暗中相信它的裁决。

嗯……这是从“狂野的互联网”中进行的一次相当大的心理转变。

于 2015-04-29T01:06:29.373 回答
9

使用OpenID ConnectUser-Managed Access

因为没有什么比不做更有效的了。

于 2016-08-10T13:27:44.113 回答