在PHP中使用正确身份验证安全登录

在PHP中使用正确身份验证安全登录,php,ruby-on-rails,security,authentication,login,Php,Ruby On Rails,Security,Authentication,Login,如何在PHP中编写/组合安全登录?他们说我不应该自己动手,所以参考谷歌提供的样本是没有用的 你是怎么做到的?假设您正在rails中构建一个世界级的应用程序,这里是否可以使用相同的库/技术 谢谢我的回答是“不要做” 这是一个非常复杂的区域,充满了潜在的安全隐患。如果你不是这个领域的专家,那么你真的只是在自找麻烦和问题 我建议您考虑使用现有的解决方案。遗憾的是,除了openid,我不知道还有什么值得推荐的。我相信你会在这里得到一些好的建议,但是…Zend框架有一个很好的起点。或者,如果您的站点将要安

如何在PHP中编写/组合安全登录?他们说我不应该自己动手,所以参考谷歌提供的样本是没有用的

你是怎么做到的?假设您正在rails中构建一个世界级的应用程序,这里是否可以使用相同的库/技术

谢谢我的回答是“不要做”

这是一个非常复杂的区域,充满了潜在的安全隐患。如果你不是这个领域的专家,那么你真的只是在自找麻烦和问题


我建议您考虑使用现有的解决方案。遗憾的是,除了openid,我不知道还有什么值得推荐的。我相信你会在这里得到一些好的建议,但是…

Zend框架有一个很好的起点。或者,如果您的站点将要安装WordPress或PHPBB,则可以利用这些技术的身份验证模块登录到站点的其他页面。

在Rails中,通常使用预先存在的库。身份验证很容易出错,而且问题已经解决了很多次,几乎不值得再次努力解决。如果您对编写自己的实现感兴趣,那么我将描述现代身份验证是如何工作的

验证用户身份的简单方法是将其密码存储在数据库中,并将其与用户提交的密码进行比较。这很简单,但难以置信的不安全。任何可以读取您数据库的人都可以查看任何人的密码。即使您设置了数据库访问控制,您(和您的用户)也容易受到任何黑客的攻击

正确的形式是在选择密码时使用加密哈希函数来处理密码,然后每次提交密码时都使用加密哈希函数。一个好的散列函数实际上是不可逆的——你不能把散列函数转换成密码。因此,当用户登录时,您获取提交的密码,对其进行散列,并将其与数据库中的散列进行比较。这样,您就不会存储密码本身。另一方面,如果用户忘记了密码,您必须重置密码,而不是将其发送给他们

然而,即使这样,也容易受到某些攻击。如果攻击者掌握了您的密码散列,并且知道您如何散列密码,那么他可以进行字典攻击:他只需将字典中的每个单词都进行散列,并将其与原始单词保持一致。这种数据结构称为彩虹表。然后,如果任何字典单词哈希值与密码哈希值匹配,攻击者可以断定密码就是哈希到该密码的字典单词。简而言之,能够读取您数据库的攻击者仍然可以使用弱密码登录帐户

解决方案是,在对密码进行哈希运算之前,将其与一个名为salt的值组合(通常是串联或异或),该值对每个用户都是唯一的。它可以是随机生成的,也可以是帐户创建时间戳或类似的东西。然后,攻击者不能使用彩虹表,因为每个密码的散列方式基本上略有不同;他必须为每一种不同的盐(实际上是每种账户)创建一个单独的彩虹表,这在计算上非常昂贵


我将附和其他回答者的建议:这不是简单的事情,你不需要这样做,因为这是以前做过的,如果你自己做,你很有可能犯错误,无意中危及你的系统安全。但是,无论出于何种原因,如果你真的真的真的想自己写一篇,我希望我已经提供了一个(不完整的!)如何完成的概要。

当你试图验证时,要看一件事,那就是你真正的目标是什么

例如,在上,我使用我的谷歌登录,这是有效的,因为他们只需要知道我是谁,他们可以相信谷歌有一个想法。因此,如果该模型适合您,那么请考虑使用OpenID,因为有各种工具可用于此

如果你必须自己做,那么会有各种各样的测试来确保它是安全的,这同样取决于你有多偏执

  • 永远不要信任用户的任何东西,除非您使用了一些严格的验证
  • 使用https来帮助保护用户的密码,你欠他们很多

我将在这里结束我的回答,因为Thom做了一个精彩的回答。

作者:Soulmerge:

我认为美国在这方面做得很好。用盐将密码散列。除此之外,还有一些关于传输层的安全思想:

  • 发送密码时使用https。这确保了没有人能在网络上捕捉到它们(或者客户端使用了一个邪恶的代理)
  • 另一种方法是在提交登录表单时使用javascript散列密码。这确保密码永远不会以明文传输。您应该在服务器上使用salt再次散列散列值。(
    md5($\u POST['postedPwHash'].$salt)

在某种程度上保护客户机-服务器事务(如果没有可用的ssl)的一个好方法是使用一次性随机密钥从凭据创建唯一哈希,然后仅将该唯一哈希发送到服务器。然后,服务器将此哈希与自己生成的哈希进行比较,而不是与真实凭据进行比较。这样可以很好地防御中间人的攻击。缺点是要做到这一点,用户必须启用JS(至少我不知道没有JS加密客户端数据的好方法)。这意味着,当它未启用时,您将需要足够的后备。您甚至可以在JS中创建表单,以确保其已启用

是一个简单的库,我写过一次,它完成了我描述的过程,尽管它可能需要一些改进

注意,这是除了使用“salting”方法和其他服务器端安全措施之外的。它也是相当脆弱的