Cookie 在 httponly 为 true 时抵抗 setcookie() 删除


Cookies resist setcookie() deletion when httponly is true

我使用 cookie 来实现"记住我"选项以登录我的网络。设置 cookie 工作正常。取消设置曾经有效。然后我用httponly cookie制作了该网站的新版本;注销在本地主机上有效,但在服务器上不起作用。我在目录"test"中运行新代码;我仍然可以使用旧代码,它适用于旧登录函数(不是新登录函数)中设置的 cookie。

以防万一这可能很重要,并且为了证明我在相关问题的答案中没有任何常见问题,例如不正确的参数、在同一页面上进行测试、已发送的标头或取消设置 cookie 时的相对时间,我展示了我的代码。首先,设置cookie的代码(新的):

...
setcookie ('login', $login, time()+60*60*24*30,'/','e-history.cz', false, true);
setcookie ('pass', $pass, time()+60*60*24*30,'/','e-history.cz', false, true);
...

我的注销脚本:

<?php
  include 'login_functions.php'; 
  logout(); 
?>

和注销功能:

  function logout() { 
    include 'library.php';  //all functions and constants
    //var_dump( headers_sent() );  //I've tested the headers, not sent yet
    checkSession();  //starts session if not started
    unset($_SESSION['login']);  //I don't need to delete the rest of the session for logout
    if(isset($_COOKIE['login']))  {
      setcookie ('login', '', 1,'/','e-history.cz', false, true);
    }   
    if(isset($_COOKIE['pass']))  {
      setcookie ('pass', '', 1,'/','e-history.cz', false, true);
    }
    header('Location:index.php'); 
  }

我已经测试了标题 - 它们工作正常。响应标头(根据Chrome的HTTP Spy扩展)包括以下内容:

Set-Cookie  pass=deleted;
expires=Thu, 01-Jan-1970 00:00:01 GMT;
path=/;
domain=e-history.cz;
httponly
Set-Cookie  login=deleted;
expires=Thu, 01-Jan-1970 00:00:01 GMT;
path=/;
domain=e-history.cz;
httponly

编辑 - 我把我以前的"答案"作为问题的一部分,因为它只工作了一段时间;我不知道为什么它现在不起作用。我在非httponly,httponly和混合cookie之间切换了几次;每次我在创建新 cookie 之前删除旧 cookie 时,请注意不要将它们不匹配。无论如何,httponly似乎没有什么区别。

我发现了一个类似的问题,说取消设置 没有服务器交互,HTTPONLY cookie 是不可能的。 从理论上讲,这应该不是问题,因为我使用 php,它可以工作 服务器端。然而,这在实践中并不容易。但是有一个 解决方案,在其答案中建议:制作其中一个饼干 与和另一个没有 httponly 属性。我害怕有 密码 cookie 中的旧值将与登录身份冲突 另一个用户,但我测试了它,它工作正常,新用户的 密码只是覆盖旧用户的密码。

问题不在于 httponly,甚至不在于我链接的任何其他问题,而是在域中 - 在"主"域 (e-history.cz) 上,"域"cookie 属性自动以点为前缀。在测试子目录 (e-history.cz/test) 上,这没有发生。结果是我可以删除主域生成的 cookie,即使测试域使用 httponly cookie,但我无法从测试子目录中删除 cookie。我明确地将点添加到域中,现在一切正常。现在对主域和测试域使用相同的 cookie 似乎不是问题 - 如果这是一个问题,我会完全删除点(通过设置 null 或 '' 来调用默认值,而不是设置的域)。