哈希和盐值 - 使用cookie验证登录

7

这基本上是一个保证,我在哈希/盐处理方面正确地完成了整个注册/登录过程。

我有一个用户表,其中包含密码、盐、令牌字段(显然还有其他字段,但这是最重要的)。在注册时,它会生成一个随机的盐和令牌,并将其放入密码字段中:

hash("sha256", $theirpostpassword.$randomgeneratedsalt);

那个随机生成的盐和令牌被存储在用户表中各自的字段中。因此,在登录时,我只从指定用户名的用户行中选择盐。然后,我进行一个查询来计算有多少行将其帖子密码与其特定盐串联起来,然后再登录他们。我相信我已经掌握了这部分内容。
现在,我想在每个页面上验证他们的登录,我会运行一个函数检查他们的cookie,以查看id-username-token格式是否与数据库中的行匹配。这意味着每次登录都会使用这些凭据设置他们的cookie。
现在,我唯一能想到的改进是在每次有效登录时更改令牌?谢谢大家的见解。

1
我会让令牌依赖于远程用户的IP,但似乎在每个请求上检查带有该信息的cookie也能正常工作。 - ncuesta
1
感谢您的快速回复,我有点反对完全进行IP检查,因为我知道有一些动态IP地址会经常更改。 - Dan LaManna
你不应该自己创建认证系统,因为很多事情可能会出错。相反,使用Facebook连接、Twitter登录、OpenID等等! - Alfred
1
@Alfred:虽然这些是非常受欢迎的身份验证方法,但谁能说你希望它们控制你的用户详细信息并希望它们不会遭受大规模数据泄露。丹的项目可能具有更小的优势,因此更不容易成为黑客攻击的目标。 - ashurexm
如果使用通用登录系统(Universal Login)被攻击,您只需要更改一个密码。但是如果每个人都有另一个登录系统,则必须更改所有密码(因为大多数人在所有网站上使用相同的密码)。 - Alfred
3个回答

4

是的,每次登录都应该更改令牌。否则,一旦令牌被窃取,帐户就会永久丢失。用户期望注销会话以使其无效,从而防止攻击他们的cookie或其他数据。

与其让令牌随机生成,不如将其作为签名,通过从用户ID、会话过期时间和cookie中需要的任何其他数据的哈希值加上盐(就像登录系统一样)来生成它。这个盐可以不必来自数据库,也可以来自数据库。它可以是一个硬编码的字符串(有时称为“pepper”)。请记住,如果cookie过期了,将其视为无效。这就是为什么令牌应该是一个签名,以确保他们没有欺骗那些数据。


1
我不同意令牌作为签名的做法。你需要让令牌无法被猜测,而唯一保证这一点的方法是使用随机性。当然,可以同时使用签名,但随机令牌非常重要。 - Cameron Skinner

2

听起来很不错,但您需要注意几点:

为使密码数据库能够抵抗暴力攻击,您可以迭代哈希函数:

$hash = $password;
for ($i = 0; $i < 1000; ++$i) {
    $hash = hash("sha256", $hash . $salt);
}

其次,确保始终使用 SSL。如果没有 SSL,攻击者很容易窃取登录 cookie。可以看看 firesheep 这个例子,就知道有多容易。

每次登录都要更改令牌,并考虑在每次请求时更改令牌,以防止会话固定和重放攻击。

您还可以从数据库中选择盐和哈希,并在服务器端执行哈希比较(而不是在数据库上),以减少与数据库的往返次数。

我建议令牌完全是随机的。您希望它无法被猜测,最好的方法是使用随机值。您也可以将令牌绑定到特定的 IP 地址,但这应该是随机令牌的补充,而不是替代品。

这就是我能想到的全部了。很高兴看到您寻求建议,而不只是将密码进行 MD5 加密并存储在数据库中!


1
检查他们的cookie,看id-username-token格式是否与数据库中的行匹配。
这样做相当昂贵,而且您没有解决会话管理的问题。过期时间设置为过去并不总是会导致cookie被删除。无论如何,可以考虑这种“记住我”类型的功能(但使用偏移路径以避免每次都呈现cookie)。
将经过身份验证的用户名存储在会话中与此方式相比,并未获得任何优势。但在对用户进行身份验证时请更改会话ID,并使用SSL来传递身份验证令牌。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接