通过PHP中的适当身份validation进行安全登

如何在PHP中编写/组合安全登录? 网站开发者指南说我不应该自己动手,所以参考谷歌提供的样本是没用的。

你是如何做到这一点的呢? 假设您正在使用rails构建世界级的应用程序,这里可以使用相同的库/技术吗?

谢谢

在Rails中,通常会使用预先存在的库。 身份validation很容易出错,问题已经解决了很多次,很难再次解决它。 如果您有兴趣编写自己的实现,那么我将描述现代身份validation的工作原理。

validation用户的简单方法是将其密码存储在数据库中,并将其与用户提交的密码进行比较。 这很简单但令人难以置信的不安全。 任何能够读取您数据库的人都可以查看任何人的密码。 即使你放入数据库访问控制,你(和你的用户)也容易受到攻击他们的人的攻击。

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

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

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

我会回应其他回答者的意见:这不是简单的事情,你不需要这样做,因为它已经完成了,如果你自己做,你就很有可能犯错并无意中妥协你的系统的安全性。 但是,无论出于什么原因,你真的想要自己写一个,我希望我提供了一个(不完整的)大纲,说明它是如何完成的。

Zend Framework有一个’Auth’模块 ,这是一个很好的起点。 或者,如果您的站点将托管WordPress或PHPBB的安装,有一些方法可以利用这些技术的身份validation模块登录站点的其他页面。

当您尝试进行身份validation时,要注意的一件事是您的真正目标是什么。

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

如果你必须自己做,那么将会有各种测试,以确保它是安全的,这取决于你想要的偏执。

  • 除非您使用了一些严格的validation,否则永远不要相信用户的任何信息。
  • 使用https来帮助保护用户的密码,你欠他们那么多。

我会在这里结束我的回应,因为Thom做了很棒的回应。

作者:Soulmerge:

我认为你在另一个问题中接受的答案很好地说明了这一点。 用盐哈希密码。 除此之外,传输层有一些安全性想法:

  • 发送密码时使用https。 这确保没有人可以在线上捕获它们( 中间人攻击或客户端使用邪恶的代理)
  • 另一种方法是在提交登录表单时使用javascript对密码进行哈希处理。 这可确保密码永远不会以明文forms传输。 您应该使用服务器上的salt再次散列哈希值。 ( md5($_POST['postedPwHash'] . $salt)

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

这个库是我写过的一个简单的库,它执行我描述的过程,尽管它可能需要一些改进。

请注意,这是使用“salting”方法和其他服务器端安全措施的补充。 它也很容易受到字典攻击,因为整个哈希过程按用户定义是程序性的,可预测的并且对用户可见(如JS一样)。

我的回答是“不要这样做”

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

我建议看一下现有的解决方案。 可悲的是,我不知道除了openid之外我会乐意推荐。 我相信你会在这里得到一些好的建议……