基于表单的网站身份验证的权威指南

时间:2008-08-02 19:51:50

标签: security http authentication language-agnostic article

网站的基于表单的身份验证

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

它应包括以下主题:

  • 如何登录
  • 如何退出
  • 如何保持登录状态
  • 管理Cookie(包括推荐设置)
  • SSL / HTTPS加密
  • 如何存储密码
  • 使用秘密问题
  • 忘记用户名/密码功能
  • 使用nonces来阻止cross-site request forgeries (CSRF)
  • OpenID
  • “记住我”复选框
  • 浏览器自动完成用户名和密码
  • 秘密网址(受摘要保护的公共URL
  • 检查密码强度
  • 电子邮件验证
  • 以及更多关于 form based authentication ...
  • 的信息

不应该包含以下内容:

  • 角色和授权
  • HTTP基本身份验证

请帮助我们:

  1. 建议子主题
  2. 提交有关此主题的优秀文章
  3. 编辑正式答案

12 个答案:

答案 0 :(得分:3643)

答案 1 :(得分:405)

最终文章

发送凭据

100%安全地发送凭据的唯一实用方法是使用SSL。使用JavaScript来散列密码是不安全的。客户端密码散列的常见缺陷:

  • 如果客户端和服务器之间的连接未加密,则您执行的所有操作均为vulnerable to man-in-the-middle attacks。攻击者可以替换传入的javascript以打破散列或将所有凭据发送到他们的服务器,他们可以听取客户端响应并完美地模仿用户等。具有可信证书颁发机构的SSL旨在防止MitM攻击。
  • 如果您不在服务器上执行其他冗余工作,则服务器收到的哈希密码为less secure

还有另一种名为 SRP 的安全方法,但它已获得专利(虽然它是freely licensed)并且几乎没有很好的实现方法。

存储密码

不要将密码以纯文本形式存储在数据库中。即使您不关心自己网站的安全性也不会。假设您的某些用户将重复使用其在线银行帐户的密码。因此,存储散列密码,并丢弃原始密码。并确保密码不会显示在访问日志或应用程序日志中。 OWASP recommends the use of Argon2是您新应用程序的首选。如果没有,则应使用PBKDF2或scrypt。最后,如果以上都不可用,请使用bcrypt。

哈希本身也是不安全的。例如,相同的密码意味着相同的哈希 - 这使得哈希查找表成为一次破解大量密码的有效方法。而是存储 salted 哈希。 salt是在散列之前附加到密码的字符串 - 每个用户使用不同的(随机)salt。 salt是一个公共值,因此您可以将哈希值存储在数据库中。有关详情,请参阅here

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

安全问题

安全问题不安全 - 避免使用它们。为什么?安全问题,密码做得更好。在此维基中的@Jens Roland answer中阅读 第三部分:使用秘密问题

会话cookie

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

Cookies can be hijacked:它们只能与客户端机器和其他通信的其他部分一样安全。它们可以从磁盘读取,在网络流量中嗅探,由跨站点脚本攻击解除,从中毒的DNS中删除,以便客户端将其cookie发送到错误的服务器。不要发送持久性cookie。 Cookie应在客户端会话结束时终止(浏览器关闭或离开您的域名)。

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

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

外部资源清单

答案 2 :(得分:155)

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

我将继续提及Mozilla提议的BrowserID(或者更确切地说,Verified Email Protocol),以便在未来找到更好的身份验证方法的升级途径。

我会这样总结一下:

  1. Mozilla是一个与values合作的非营利组织,可以很好地找到解决此问题的方法。
  2. 今天的现实是大多数网站都使用基于表单的身份验证
  3. 基于表单的身份验证有一个很大的缺点,即phishing的风险增加。要求用户将敏感信息输入由远程实体控制的区域,而不是由其用户代理(浏览器)控制的区域。
  4. 由于隐式信任浏览器(用户代理的整个想法是代表用户行事),因此它们可以帮助改善这种情况。
  5. 这里阻碍进展的主要力量是deployment deadlock。必须将解决方案分解为自己提供一些增量收益的步骤。
  6. 用于表达内置于互联网基础设施中的身份的最简单的分散方法是域名。
  7. 作为表达身份的第二级,每个域管理自己的一组帐户。
  8. 表单“account @ domain”简洁明了,并受到各种协议和URI方案的支持。当然,这种标识符通常被认为是电子邮件地址。
  9. 电子邮件提供商已经是在线事实上的主要身份提供商。如果您可以证明您控制该帐户的相关电子邮件地址,则当前的密码重置流程通常可让您控制帐户。
  10. 建议使用经过验证的电子邮件协议,以提供一种基于公钥加密的安全方法,以简化向域B证明您在域A拥有帐户的过程。
  11. 对于不支持已验证电子邮件协议的浏览器(目前全部都是这样),Mozilla提供了一个在客户端JavaScript代码中实现协议的垫片。
  12. 对于不支持已验证电子邮件协议的电子邮件服务,该协议允许第三方充当可信中间人,断言他们已验证用户对帐户的所有权。拥有大量此类第三方是不可取的;此功能仅用于允许升级路径,并且电子邮件服务本身更愿意提供这些断言。
  13. Mozilla提供自己的服务,就像这样一个值得信赖的第三方。实施验证电子邮件协议的服务提供商(即依赖方)可能会选择信任Mozilla的断言。 Mozilla的服务使用传统方式发送带有确认链接的电子邮件来验证用户的帐户所有权。
  14. 除了他们可能希望提供的任何其他身份验证方法之外,服务提供商当然可以提供此协议作为选项。
  15. 这里寻求的一个重要的用户界面好处是“身份选择器”。当用户访问网站并选择进行身份验证时,他们的浏览器会向他们显示他们可能用来向网站标识自己的电子邮件地址(“个人”,“工作”,“政治激进主义”等)。
  16. 作为此项工作的一部分,正在寻求的另一个重大用户界面优势是helping the browser know more about the user’s session - 他们当前主要登录的是谁 - 因此它可能会在浏览器中显示Chrome。
  17. 由于该系统的分布式特性,它避免了对Facebook,Twitter,Google等主要网站的锁定。任何个人都可以拥有自己的域名,因此可以充当自己的身份提供者。
  18. 这不是严格的“基于表单的网站身份验证”。但是,从基于表单的身份验证的当前规范过渡到更安全的东西:浏览器支持的身份验证。

答案 3 :(得分:130)

我以为我会分享这个我发现工作正常的解决方案。

我称之为 Dummy Field (虽然我没有发明这个,所以不要相信我)。

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

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

诀窍是欺骗机器人认为必须将数据插入必填字段,这就是我将输入命名为“email”的原因。如果您已经有一个名为email的字段,那么您应该尝试将虚拟字段命名为“company”,“phone”或“emailaddress”。只需选择一些您不需要的东西,以及人们通常认为可以填写到网络表单中的东西。现在使用CSS或JavaScript / jQuery隐藏input字段 - 无论哪种方式最适合您 - 只需将输入type设置为hidden或其他方式不会堕落。

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

示例:

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

如果是机器人:机器人会看到一个类型为text且名称为email的字段(或者您称之为它的任何字段)并且会在逻辑上试图用适当的数据填充它。如果您使用一些花哨的CSS设置输入表单的样式并不关心,Web开发人员会一直这样做。无论虚拟字段中的值是什么,只要它大于0个字符,我们就不在乎。

我在留言簿上结合CAPTCHA使用了此方法,之后我没有看过任何一封垃圾邮件帖子。我之前使用过CAPTCHA解决方案,但最终每小时产生了大约5个垃圾邮件。在表单中添加虚拟字段已停止(至少到现在为止)所有垃圾邮件都会出现。

我相信这也可以在登录/身份验证表单中使用。

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

您也可以通过让虚拟区域可见但在屏幕边界之外可以稍微改变一下,但这完全取决于您。

要有创意!

答案 4 :(得分:75)

我不认为上面的答案是“错误的”,但是有大量的认证没有被触及(或者更重要的是“如何实现cookie会话”,而不是“有哪些选项可用以及是权衡取舍“。

我建议的编辑/答案是

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

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

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

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

所以......

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

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

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

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

  2. SRP - 没有受信任的第三方的智能密码身份验证。但在这里,我们进入了“使用双因素身份验证更安全,即使成本更高”

  3. SSL客户端 - 为客户提供公钥证书(在所有主流浏览器中都支持 - 但会引发有关客户端计算机安全性的问题)。

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

答案 5 :(得分:51)

答案 6 :(得分:51)

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

创建哈希值的速度越快,任何暴力检查程序的工作速度就越快。因此较慢的哈希会减慢暴力迫使。对于较长的密码(8位+),慢速哈希算法会使强制执行变得不切实际

答案 7 :(得分:46)

我最喜欢的身份验证系统规则:使用密码而不是密码。容易记住,难以破解。 更多信息:Coding Horror: Passwords vs. Pass Phrases

答案 8 :(得分:21)

我想根据防御深度添加一个我用过的建议。您不需要为常规用户提供与管理员相同的auth&amp; auth系统。您可以在单独的URL上使用单独的登录表单,为要授予高权限的请求执行单独的代码。这个可以做出对普通用户来说完全痛苦的选择。我使用的一个实际上是加密管理员访问的登录URL并通过电子邮件向管理员发送新URL。立即停止任何暴力攻击,因为您的新URL可能是任意困难的(非常长的随机字符串),但您的管理员用户唯一的不便是在他们的电子邮件中跟踪链接。攻击者不再知道POST到哪里。

答案 9 :(得分:13)

我不知道最好是回答这个问题作为答案还是评论。我选择了第一个选项。

关于第一个答案中的po strong PART IV:忘记密码功能,我会指出时间攻击。

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

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

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

答案 10 :(得分:12)

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

  • &#34;在公司, intra - 网络设置中,&#34;大多数(如果不是全部)可能不适用!

许多公司部署&#34;仅限内部使用&#34;有效地,&#34;企业应用程序&#34;恰好是通过URL实现的。这些网址(据说......)只能在公司的内部网络中解析。&#34; (哪个网络神奇地包含了所有与VPN相关的&#39;公路战士。&#39;)

当用户尽职地连接到上述网络时,他们的身份(&#34;身份验证&#34;)是[已...]&#34;最终知道,&# 34;他们的许可(&#34;授权&#34;)可以执行某些操作......例如...&#34;访问此网站。&#34;

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

从您的角度来看,您只是知道这一点:任何合法地在您的网站结束的人必须伴随着[环境变量神奇地变化]包含...]&#34;令牌。&#34; (即。缺少此类令牌必须是404 Not Found的直接理由。)

令牌对你来说毫无意义,但是,是否需要出现,&#34;存在适当的手段&#34;您的网站可以通过它[权威地]询问知道的人(LDAP等)&#34;关于您可能拥有的任何和每个(!)问题。换句话说,你利用任何&#34;本土逻辑。&#34;相反,你询问管理局并暗中信任其判决。

嗯......这是相当来自&#34;野性和毛茸茸的互联网的心理转换。&#34;

答案 11 :(得分:5)

使用OpenID ConnectUser-Managed Access

因为没有比没有做更有效的事情。