7

我的代码中有很多实例需要快速访问登录的用户名和用户 ID。我目前使用cookies。这不安全。

我认为会话将​​是一个解决方案,但会话过期。

另一种选择是将唯一令牌存储在 cookie 中,然后与数据库中存储的令牌匹配,以检索登录的用户数据。这是最安全的解决方案,但我看到的问题是,在我的代码中有很多次需要登录的用户名和用户 ID,但一直查询会耗尽不必要的资源(这是真的吗?)

解决办法是什么?

4

3 回答 3

5

我将尝试将评论中所说的所有内容合并为一个答案。因此,请通过支持他们的答案/评论来向其他有帮助的用户表达一些爱!我还将简要概述会话的工作原理,以使答案对更广泛的受众有用。

当用户登录网站时,会创建一个会话来识别他们。在 PHP 中通过创建会话 ID 来处理会话,然后将该 ID 与服务器端的变量存储相关联,在 PHP 脚本中使用$_SESSION超全局访问该变量。会话 ID 存储在客户端的 cookie 中,并标识他们的会话。

为了保持安全,会话 ID 必须是唯一的、随机的和保密的。如果攻击者猜到了您的会话 ID,他们可以使用相同的 ID 在他们自己的计算机上创建一个 cookie,并接管您的会话。他们会以您的身份登录!这显然很糟糕,因此 PHP 使用强大的随机数生成器来创建这些会话 ID。为了使事情更安全,您可以在站点范围内启用 SSL,并通知浏览器只通过 SSL 发送 cookie,使用 HTTPS-only 标志。不过,这对您的网站来说可能有点矫枉过正。

为了防止泄露的会话 ID 永远有用,或者在你去商店后坏人潜入你的房间,会话使用超时。最好让它们在相当短的时间后过期 - 根据您的安全要求,在 10 到 60 分钟之间。您可以在每次查看页面时重置超时,这样活动用户就不会被注销。

为了让用户被记住(即“记住我”复选框),您需要提供一个用作身份验证令牌的 cookie。请记住,从所有意图和目的来看,此令牌与拥有您的密码相同。这意味着如果坏人窃取了 cookie,他们可以登录您的帐户。为了使这个选项安全,我们可以使用一次性令牌。这些令牌应该是一次性的、随机的、长的和秘密的。将它们视为密码!

以下是如何实现它们:

  1. 生成随机令牌。/dev/urandom如果可以,请使用,否则您需要数百个值mt_rand才能获得足够“随机”的东西,然后使用 SHA1 对结果字符串进行散列以生成令牌。
  2. 使用强密码散列算法(例如 PBKDF2 或 bcrypt)来创建令牌的散列。不要为此目的使用 SHA1 或 MD5 - 它们不是为散列密码而设计的!
  3. 将哈希值连同它所属的用户的 ID 和它的创建日期一起插入到数据库表中。
  4. 在用户端的 cookie 中设置令牌。
  5. 当用户访问该站点、未登录并且检测到登录令牌 cookie 时,使用您在步骤 2 中使用的相同算法对来自 cookie 的令牌值进行哈希处理,并在数据库中查找它。如果它与条目匹配,则将该用户作为该 ID 登录。
  6. 从数据库中删除条目并发出一个新条目(返回步骤 1)。

您还应该运行一个脚本来查找非常旧的会话令牌(例如 3 个月或更长时间)并删除它们。这将要求用户在长时间不活动后返回时再次登录。

有关此问题的详细说明以及有关安全 Web 表单登录系统的更多重要信息,请阅读基于表单的网站身份验证的权威指南并查看OWASP 项目

于 2012-07-18T12:23:46.693 回答
3

如果客户端不需要它,请确保它不会在那里结束。

由于 userId 特定于登录用户而不是特定计算机,因此 cookie 似乎不是可行的方法。

PHP 中的基本身份验证通常通过会话完成,因此您也可以将 userId 添加到会话中。

如果会话时间太短,请增加会话时间。

于 2012-07-18T11:46:43.417 回答
-5

我将这些信息存储在数据库中,并在启动时在我的全局对象注册表中创建一个用户对象。用户对象包含用户名或电子邮件等信息,并允许更改这些信息。登录状态本身存储在会话中,也存储在 cookie 中。

于 2012-07-18T11:45:43.767 回答