我们认为Stack Overflow不仅应该是非常具体的技术问题的资源,而且还应该是关于如何解决常见问题变体的一般指导原则。 “基于表单的网站身份验证”应该是此类实验的一个很好的主题。
答案 0 :(得分:3643)
答案 1 :(得分:405)
100%安全地发送凭据的唯一实用方法是使用SSL。使用JavaScript来散列密码是不安全的。客户端密码散列的常见缺陷:
还有另一种名为 SRP 的安全方法,但它已获得专利(虽然它是freely licensed)并且几乎没有很好的实现方法。
不要将密码以纯文本形式存储在数据库中。即使您不关心自己网站的安全性也不会。假设您的某些用户将重复使用其在线银行帐户的密码。因此,存储散列密码,并丢弃原始密码。并确保密码不会显示在访问日志或应用程序日志中。 OWASP recommends the use of Argon2是您新应用程序的首选。如果没有,则应使用PBKDF2或scrypt。最后,如果以上都不可用,请使用bcrypt。
哈希本身也是不安全的。例如,相同的密码意味着相同的哈希 - 这使得哈希查找表成为一次破解大量密码的有效方法。而是存储 salted 哈希。 salt是在散列之前附加到密码的字符串 - 每个用户使用不同的(随机)salt。 salt是一个公共值,因此您可以将哈希值存储在数据库中。有关详情,请参阅here。这意味着您无法向用户发送他们忘记的密码(因为您只有哈希)。除非您已对用户进行身份验证,否则不要重置用户的密码(用户必须证明他们能够阅读发送到存储(和验证的)电子邮件地址的电子邮件。)
安全问题不安全 - 避免使用它们。为什么?安全问题,密码做得更好。在此维基中的@Jens Roland answer中阅读 第三部分:使用秘密问题 。
用户登录后,服务器会向用户发送会话cookie。服务器可以从cookie中检索用户名或id,但是没有其他人可以生成这样的cookie(TODO解释机制)。
Cookies can be hijacked:它们只能与客户端机器和其他通信的其他部分一样安全。它们可以从磁盘读取,在网络流量中嗅探,由跨站点脚本攻击解除,从中毒的DNS中删除,以便客户端将其cookie发送到错误的服务器。不要发送持久性cookie。 Cookie应在客户端会话结束时终止(浏览器关闭或离开您的域名)。
如果要对用户进行自动登录,可以设置持久性cookie,但它应与完整会话cookie不同。您可以设置用户已自动登录的附加标志,并且需要登录才能进行敏感操作。这对于希望为您提供无缝,个性化购物体验但仍能保护您的财务详细信息的购物网站而言非常受欢迎。例如,当您返回访问亚马逊时,他们会向您显示一个看起来像您已登录的页面,但当您下订单(或更改您的送货地址,信用卡等)时,他们会要求您确认你的密码。
另一方面,银行和信用卡等金融网站只有敏感数据,不允许自动登录或低安全模式。
答案 2 :(得分:155)
首先,一个强烈的警告,这个答案不是最适合这个问题的答案。绝对不应该是最好的答案!
我将继续提及Mozilla提议的BrowserID(或者更确切地说,Verified Email Protocol),以便在未来找到更好的身份验证方法的升级途径。
我会这样总结一下:
@
domain”简洁明了,并受到各种协议和URI方案的支持。当然,这种标识符通常被认为是电子邮件地址。这不是严格的“基于表单的网站身份验证”。但是,从基于表单的身份验证的当前规范过渡到更安全的东西:浏览器支持的身份验证。
答案 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等)。
这避免了任何需要“会话”或cookie的需要,因为浏览器本身每次都会重新加密通信。它是最“轻量级”的开发方法。
但是,除了公共的低价值服务之外,我不建议这样做。这是上面一些其他答案的问题 - 不要尝试重新实现服务器端身份验证机制 - 这个问题已经解决并且得到大多数主流浏览器的支持。不要使用cookies。不要在您自己的手工数据库中存储任何内容。根据请求,只询问请求是否经过身份验证。其他所有内容都应该由配置和第三方可信软件支持。
所以......
首先,我们将初始创建帐户(带密码)与随后重新检查密码混淆。如果我是Flickr并且是第一次创建您的站点,则新用户可以访问零值(空白Web空间)。如果创建帐户的人谎称他们的名字,我真的不在乎。如果我正在创建医院内联网/外联网的帐户,则其价值在于所有医疗记录,因此我 关心帐户创建者的身份(*)。
这是非常困难的部分。 唯一体面的解决方案是一个信任网。例如,您作为医生加入医院。您创建一个托管在您的照片,护照号码和公钥的某个地方的网页,并使用私钥对它们进行哈希处理。然后,您访问医院,系统管理员查看您的护照,查看照片是否与您匹配,然后使用医院私钥对网页/照片哈希进行哈希处理。从现在开始,我们可以安全地交换密钥和令牌。任何信任医院的人都可以(有秘密酱BTW)。系统管理员还可以为您提供RSA加密狗或其他双因素身份验证。
但这是一个麻烦的很多,而不是非常的web 2.0。但是,这是创建可以访问非自创的有价值信息的新帐户的唯一安全方式。
答案 5 :(得分:51)
散列时,不要使用快速哈希算法,如MD5(存在许多硬件实现)。使用像SHA-512这样的东西。对于密码,较慢的哈希值更好。
创建哈希值的速度越快,任何暴力检查程序的工作速度就越快。因此较慢的哈希会减慢暴力迫使。对于较长的密码(8位+),慢速哈希算法会使强制执行变得不切实际
答案 6 :(得分:51)
答案 7 :(得分:46)
我最喜欢的身份验证系统规则:使用密码而不是密码。容易记住,难以破解。 更多信息:Coding Horror: Passwords vs. Pass Phrases
答案 8 :(得分:21)
我想根据防御深度添加一个我用过的建议。您不需要为常规用户提供与管理员相同的auth&amp; auth系统。您可以在单独的URL上使用单独的登录表单,为要授予高权限的请求执行单独的代码。这个可以做出对普通用户来说完全痛苦的选择。我使用的一个实际上是加密管理员访问的登录URL并通过电子邮件向管理员发送新URL。立即停止任何暴力攻击,因为您的新URL可能是任意困难的(非常长的随机字符串),但您的管理员用户唯一的不便是在他们的电子邮件中跟踪链接。攻击者不再知道POST到哪里。
答案 9 :(得分:13)
我不知道最好是回答这个问题作为答案还是评论。我选择了第一个选项。
关于第一个答案中的po strong PART IV:忘记密码功能,我会指出时间攻击。
在记住您的密码表单中,攻击者可能会检查完整的电子邮件列表并检测哪些已注册到系统(请参阅下面的链接)。
关于忘记密码表格,我想补充一点,使用一些延迟功能在成功和不成功查询之间等于时间是个好主意。
答案 10 :(得分:12)
我想补充一条非常重要的评论: -
许多公司部署&#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 Connect或User-Managed Access。
因为没有比没有做更有效的事情。