记住我功能的最佳实践[重复]

Posted

技术标签:

【中文标题】记住我功能的最佳实践[重复]【英文标题】:Best practice for remember me feature [duplicate] 【发布时间】:2011-04-01 16:13:51 【问题描述】:

我在 cookie 中使用了 2 个变量(7 天到期),即用户 ID 和哈希。哈希是用户代理和用户 ID 的 sha1 编码。在这种情况下,一些黑客可以登录谁知道被盗 cookie 的浏览器。我应该遵循哪种方式或哪种做法最适合记住我的安全问题?

【问题讨论】:

相关:***.com/search?q=php+session+hijacking 您应该尽可能重用现有的身份验证框架,因为它确实很复杂。比如看看github.com/delight-im/PHP-Auth 【参考方案1】:

就个人而言,我创建了一个随机散列并将其存储在“记住我”表中。该表还包含用户代理、用户 ID 和 IP 地址。每次我从记住我功能重新登录用户时,我都会检查两者。如果用户手动注销,我只需从表中删除该行。然后,如果他们再次登录,它会创建一个新的随机散列。真的没有办法用记住我的系统来对付嗅探数据包的人(除非你使用带有 HTTPS only 标志集的安全 cookie)。因此,请使用仅限 HTTPS 的 cookie 的安全连接。如果你不能,那么至少让散列随机,所以如果发现它,你至少可以生成一个新的散列来终止该登录...

【讨论】:

不是我,但我总是对这样的实现保持警惕,因为它假设用户代理和 ip 等变量通常不是常量。我不会将此定义为解决方案,而是更多的解决方法 很公平。但是在没有 HTTPS 唯一 cookie 的情况下,真的有更好的方法来尝试验证来源吗? 不幸的是,我还没有看到或听说过一个,我认为如果你想要一个记住我的功能,它应该只访问低重要性区域,因为滥用的记住我功能有无数的安全问题例如共享计算机等。在电话上为 grAmmar 道歉。【参考方案2】:

您最终可以使用会话来存储用户状态。但是长时间保持会话会导致同样的问题,当会话 id 会被盗。您可以将 cookie 信息与其他一些 - 例如浏览器或 IP 地址相结合,但是当用户没有静态 IP 时,它会导致问题。

无论如何,持有会话 ID 比将用户的 sha1 结尾密码放入 cookie 更安全。

【讨论】:

幸运的是,OP 根本没有谈论密码 :) 但是,会话 ID 在这里可能有用。 长时间运行的会话几乎总是一个坏主意。它们为特定的 DOS 攻击打开了大门,因为您可以消耗大量的存储空间,因为 PHP 在达到时间限制之前无法 GC 会话。在某些情况下这是必要的,但在大多数情况下,这不是一个好主意......【参考方案3】:

HMAC

我通常这样做,所以我没有任何东西可以存储在服务器端的数据库或类似的东西上。

您必须生成成为您的“密钥”的随机字符串,并且您必须将其存储在服务器端(可能在配置 php 脚本中作为常量)并且您永远不会告诉任何人。我将把这个密钥称为SECRET_KEY

那么你的cookie必须设置两个值:

USER_ID: 自动登录用户的用户id HASHUSER_IDSECRET_KEY 的安全加密哈希。因此,例如,md5(USER_ID . "-" . SECRET_KEY)。 (首选不同于 md5 的内容,例如 sha1 或 sha256)。

所以你的最终 cookie 可能是:USER_ID:HASH

然后,当您必须检查 cookie 是否是真正的记住我 cookie 时,您必须这样做:

function isCookieGenuine($cookie_value) 
  list($value, $hash) = explode(':', $cookie_value, 2);

  if (md5($value . "-" . SECRET_KEY) == $hash)
    return true;
  else
    return false;

关键是只有你可以生成通过此检查的哈希,因为哈希不仅需要USER_ID,还需要SECRET_KEY 除了服务器之外的任何人都不知道! :)

如 cmets 中所述,您可以通过使用 PHP >= 5.1.2 中的 hash_hmac 函数来执行此操作:http://us.php.net/manual/en/function.hash-hmac.php

【讨论】:

太糟糕的数组解引用在 PHP 中还不起作用(它仅在中继中实现)。所以你可以改为list($value, $hash) = explode(':', $cookie_value, 2);。如果您为每个用户实施不同的“秘密”,那么对于安全性可能会更好(因为这样一次对秘密的妥协不会为每个用户打开大门)。哦,PHP 有一个内置的 hash_hmac function 来做这件事...... @ircmaxell,为您的评论 +1(我开始忘记这些事情......我不再写 php 了:))。我正在整合您的提示。相反,我不同意为每个用户创建不同秘密的想法。虽然它显然更安全,但在我看来,在这种情况下优势微乎其微。【参考方案4】:

虽然您可以散列 user_id 和 secret_key,但截获此 cookie 的任何人都可以登录您的应用程序。除此之外,您还可以让您的记住我的 cookie 很快过时。没有人喜欢陈旧的饼干。

您可以将每个用户上次访问的时间戳存储在您的数据库和 cookie 中。每次您读取 cookie 以使用户登录时,您都会检查两个时间戳是否匹配。如果他们不这样做,则拒绝该用户。如果有,请更新时间戳。

使用此方法,任何时候您的用户返回您的网站,所有旧的 cookie 都会过时。截获 cookie 的黑客现在拥有一个毫无价值的陈旧 cookie,因为他不知道当前 cookie 中的确切时间戳。当然,黑客可以在用户重新登录之前尽可能多地使用新的 cookie。

//check for cookie
if(isset($_COOKIE['remember_me'])) 
   // get hash and time stamp from cookie
   $hash = substr($_COOKIE['remember_me'],0,40);
   $last_visit = substr($_COOKIE['remember_me'],41);

   // query your db with $hash and $last_visit

   // if hash and time stamp match up
      // log in

      // store the current time stamp in a variable to use for both
      $time = date("Y-m-d H:i:s");
      // update the time stamp in your cookie
      $cookie = $pass . "-" . $time;
      setcookie('remember_me', $cookie, time()+60*60*24*100, '/');
      // update the time_stamp in your database
   else 
      // remove the remember me cookie
      setcookie('remember_me', '', time()-42000, '/')
   

这种方法提供了少量的安全性,当然应该与其他答案中提出的方法一起使用。散列密钥应存储在 cookie 中。记住我的 cookie 不能完全安全,因此对高度敏感数据或应用程序功能的任何其他访问都需要重新输入密码。

我还建议将您的 cookie 命名为“remember_me”以外的其他名称,以使其更难找到。虽然它不会增加太多安全性(如果有的话),但将您的 cookie 命名为“ht33424”所花费的时间与将其命名为“remember_me”或“hack_me”的时间一样长。

【讨论】:

对不起,但我认为我不喜欢这个答案,除非我误解了它的逻辑,这依赖于用户在黑客有时间复制和执行页面之前加载新页面.在真正的用户会话结束时,会有一个很大的劫持窗口,即使在会话期间,在页面加载之间滑入也不应该太难。这将为真正的用户创建不寻常的页面行为。重命名 cookie 变量名称是安全的,因为它晦涩难懂,而且浪费时间。 (续) ... 这可能是另一层会有所帮助,但坚定的黑客不会被它吓倒。由于我上面提到的原因,它也不是 100% 的故障保护。对于对敏感信息和功能的敏感且可能具有破坏性的访问,我不建议将此方法作为 100% 安全的解决方案,而只是略微改进。 对于坚定的黑客来说,没有任何方法是 100% 安全的。正如你所说,这实际上只是尝试让我们更接近 100% 的一层。这意味着与其他方法一起使用,其中许多方法在其他答案中提供。散列密钥绝对应该存储在 cookie 中,并且应该需要重新输入密码才能额外访问敏感信息和功能。 如果没有这种方法,黑客仍然可以在页面加载之间溜走,为真正的用户创建不寻常的页面行为。这种方法会强制黑客在每次真正用户登录时重新拦截 cookie。由于这对于有决心的黑客来说可能不是问题,因此这种方法仅对此处讨论的其他方法增加了一点安全性。【参考方案5】:

您可以在 cookie 上简单地将到期日期设置为现在加上一年,然后在所有敏感区域都有一个输入密码字段,就像亚马逊使用的实现一样。被劫持的 cookie 将授予访问权限,但购买或修改任何个人内容需要重新输入密码。

“记住我”表的问题在于,如果黑客可以访问此表,他可以创建并登录任意数量的帐户。您可以说它增强了记住我功能的安全性,但需要权衡软化膝盖安全区域的风险。

【讨论】:

以上是关于记住我功能的最佳实践[重复]的主要内容,如果未能解决你的问题,请参考以下文章

注销和记住会话的最佳 Worklight 实践

放置 Document Ready 功能的最佳实践 [重复]

PHP单例类的最佳实践[重复]

连接 MongoDB 的最佳实践 [重复]

重复 SQL 语句的最佳实践

深度学习最佳实践