【问题标题】:How to secure User ID inside cookie value如何保护 cookie 值中的用户 ID
【发布时间】:2014-08-07 03:34:42
【问题描述】:

登录用户后,我将用户 ID 保存在 cookie ($_COOKIE['user_id']) 中,然后 mysql 检查 cookie 中是否存在 isset user_id 以及数据库中是否存在 user_id:

SELECT * FROM users WEHERE user_id = '$_COOKIE[user_id]'

它可以工作,但是每个客户端都可以更改cookie值,因此客户端可以将cookie user_id设置为1或2,3,4并且它将被登录,因此他们可以破解页面。

我想以某种方式散列或保护我的 cookie user_id 值。我希望你能理解我。 你能给我一些建议吗?

【问题讨论】:

  • 为什么在这种情况下你需要它在 cookie 中而不是 - 例如 - 一个会话?
  • 会话将过期,我需要在用户返回页面后自动登录...
  • 好的,那么您基本上需要对其进行加密,向 cookie 添加校验和(包括用户 ID 和密码),或者在 cookie 中使用您可以查看的完全随机值在数据库中。
  • SQL 注入顺便说一句,最好使用准备好的语句。

标签: php mysql sql cookies


【解决方案1】:

不要在 cookie 中这样做。在 cookie 中保存一个哈希并将相应的用户 ID 存储在您的数据库中。您无法确保 cookie 安全。

为了更清楚:

当用户登录时,在数据库中为他存储一个唯一的哈希值。这可能是这样的:sha512('9a7fd98asf'.time().$username)。这也是您保存在 cookie 中的值。您知道用户已登录,如果他在数据库中有这样的令牌并且它是否与 cookie 中的值匹配。这实际上就是会话的处理方式。

【讨论】:

  • 我的用户已经存储在数据库中,你的意思是“在 cookie 中保存一个哈希”,如何对我的 cookie 进行哈希处理?以哪种方式?
  • 我看到这种方法的问题是,如果用户从第二台计算机登录,使用新哈希更新数据库将使他的第一次登录无效。如果您只考虑何时真正需要在数据库中重新生成哈希值,可能是可以修复的。
  • 好吧,如果您在那里没有任何安全问题,您可以简单地保存并允许他使用登录时生成的 all 哈希。当然,他需要从每台电脑登录一次,但这是 cookie 的特性。
  • 如果客户端没有用户信息,只有一个hash,当用户返回时,你怎么知道hash是给哪个用户的?
【解决方案2】:

您可以存储一个名为“user_hash”的附加 cookie:

$_COOKIE['user_hash']=sha1($user_id . md5($user_pass . $salt1) . $salt2);

使用一些常量 $salt 值。

使用user_id cookie时,首先检查user_hash是否与数据库中存储的用户登录信息匹配。

由于 sha1 是不可逆的,因此无法从中导出密码。

【讨论】:

  • 所以你说每次登录后我都必须在数据库和cookie中保存sha1($user_id . md5($user_pass . $salt1) . $salt2);
  • 不——它源自存储在数据库中的 $user_id 和 $user_pass。在您同意使用 $_COOKIE['user_id'] 之前,从数据库中加载 $user_id 和 $user_pass,计算 sha1,并检查 $_COOKOE['user_hash'] 是否相同。没有密码,令牌是无法伪造的。
【解决方案3】:

Cookie 容易受到多种类型的攻击,包括有人从某个用户那里窃取 Cookie,然后将其呈现出来以冒充该用户。如果您要改用会话,则必须使用会话 cookie 或 URL,从安全角度来看,这两者都是有问题的。

您可能做的最好的事情是加密 cookie,以便您稍后在读取 user_id 时对其进行解密。这将确保用户不能随意更改其 user_id。但是,这并不能防止一个用户使用另一个用户的 cookie 中的数据。

为了防止回复攻击(来自同一用户或不同用户),除了存储 user_id 之外,您还希望在 cookie 中存储到期时间。当您取回 cookie 时,您可以解密并获得所需的时间。这确实意味着这种类型的重放攻击在 cookie 有效的时间内是可能的。

对于加密/解密,您可以搜索并找到如何使用您所使用的语言正确执行此操作。您仍然需要针对损坏的 cookie 进行测试(在这种情况下,您可以假设用户未通过身份验证)。

【讨论】:

    【解决方案4】:

    您想使用无意义的标记。这是最安全的方式,因为令牌本身是没有意义的,本身不能被攻击。因为令牌还需要与相关数据一起存储在服务器上,这也使服务器对登录具有最终控制权;因为服务器可以随时撤消活动令牌(您不能撤消仅存储自包含用户 ID 的 cookie)。

    标准的 PHP 会话是一个毫无意义的标记,在大多数情况下都可以正常工作。会话甚至可以配置为持续很长时间,您甚至可以将会话存储后端更改为数据库或任何您想要的自定义后端。
    如果出于某种原因,您需要其他东西,您仍然需要相同的想法:

    • 生成一个完全随机、无意义的值
    • 将其连同属于哪个用户一起存储在数据库中
    • 将 cookie 中的令牌发送给客户端

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-07
      • 2011-08-24
      • 2023-04-03
      • 2012-05-03
      • 1970-01-01
      • 1970-01-01
      • 2012-09-25
      相关资源
      最近更新 更多