删除 Javascript 中的 cookie 是同步的吗?

Is deleting a cookie in Javascript Synchronous?

我或多或少有一份 Javascript Delete Cookie Before Reload or Redirect 的副本,但从未得到任何答案。

我继承了一些 javascript 执行以下操作的代码

 function delete_cookie ( cookie_name )
  {
     var cookie_date = new Date ( );  // current date & time
     cookie_date.setTime ( cookie_date.getTime() - 1 );
     document.cookie = cookie_name += "=; expires=" + cookie_date.toGMTString();
  }
  delete_cookie ( "sessionId" );
  window.location ="https://some_redirect";

问题是重定向页面的 GET 包含原始 cookie(显然没有被删除),服务器只是不断地响应 delete/redirect 代码(在 chrome/canary/IE).如果它有所作为,cookie 最初设置为 "sessionId=;"

Cookie 始终设置为以下模式

"Set-Cookie: sessionId=%s;path=/;%s postId=%s;%s " "\r\n"

我知道 toGMTString 已被弃用,直接设置为 window.location 可能并不理想。这些似乎都与问题无关。

如果我将 window.location 调用放在 setTimeout 中,或者如果我将其作为 delete_cookie 的回调来执行,那么一切都会神奇地完美运行。但是为什么?

似乎可以可靠地工作

function delete_cookie (cookie_name, callback)
{ 
   ...
   callback();
 }
delete_cookie( "sessionID", doRedirect);

其中 doRedirect 只是 window.location

这种行为是预期的吗?我的假设是,当 cookie 设置为过去的到期日期时,它会在继续执行代码之前被删除。是否有更好的机制来确保在重定向之前已删除 cookie?

编辑:附加信息

按如下方式修改 cookie 无济于事

       function delete_cookie ( cookie_name )
       {
+         var retries = 0;
          var cookie_date = new Date ( );  // current date & time
          cookie_date.setTime ( cookie_date.getTime() - 1 );
          document.cookie = cookie_name += "=; expires=" + cookie_date.toGMTString();
+      
+         while (document.cookie.indexOf("sessionId=") != -1)
+         {
+            retries +=1;
+            if (retries == 1000) 
+            { 
+                console.log("giving up after 1000 retries");
+                break;
+            }
+
+         }
+         console.log("We had to retry "+retries+" time(s)");
       }
       delete_cookie ( "sessionId" );

控制台输出为

giving up after 1000 retries

We had to retry 1000 time(s)

有趣的是,如果我在客户端进行调试,我会看到以下内容

金丝雀(版本 42.0.2302.2 金丝雀(64 位))

从开发控制台 "Resources" 选项卡提供 javascript 重定向代码后,在 Cookies->10.0.11.118 下显示 "This site has no cookies."

但是在 chrome 的单独选项卡中://settings/cookies 我仍然可以看到

Name:   sessionId 
Content:     
Domain: 10.0.11.118 
Path:   / 
Send for:   Any kind of connection 
Accessible to script:   Yes 
Created:    Thursday, February 12, 2015 at 12:26:07 PM 
Expires:    When the browsing session ends

这与您的 cookie 无关,而是时间。

你所做的不是,而是毫秒。

因此,当您要求它提供 GMT 时间格式时,在大多数情况下,它甚至不知道现在时间格式和毫秒前时间格式之间的区别。它会显示与毫秒前相同的时间并且不会删除cookie,因为cookie 尚未过期。

您想做的是回到过去一千毫秒,也就是一秒,回到过去。

var cookie_date = new Date ( );
alert(cookie_date.toGMTString()); 
//outputs Sat, 14 Feb 2015 18:07:45 GMT

cookie_date.setTime ( cookie_date.getTime() - 1 );
alert(cookie_date.toGMTString()); 
//outputs Sat, 14 Feb 2015 18:07:45 GMT

var good_cookie_date = new Date ( );     
alert(good_cookie_date.toGMTString());
//outputs Sat, 14 Feb 2015 18:07:45 GMT

good_cookie_date.setTime ( good_cookie_date.getTime() - 1000 );
alert(good_cookie_date.toGMTString());
//outputs Sat, 14 Feb 2015 18:07:44 GMT

See fiddle example

Google Chrome

我在我的机器上试过你的代码。我设置了带有和不带有路径=/的cookie。在这两种情况下,它都工作正常。即代码先删除cookie,再重定向。

Firefox

我可以在 firefox 中重现该问题。

正如你所说,你在设置 cookie 时使用了 path=/,我在取消设置时使用了相同的格式。

document.cookie = cookie_name += "=; expires=" + cookie_date.toGMTString() + "; path=/";

它工作了一次,然后又出现了问题。我可以将问题与缓存联系起来。因为当我将重定向行更新为

window.location ="redirect.html?"+Math.random();

一切开始顺利进行。随机字符串避免缓存。

我尽量让这个答案尽可能通用,以下问题之一,或者多个 cookie 具有相同的密钥,或者没有通过足够的有效期是你的问题


cookie 没有被删除的可能性有多种。

您可以拥有多个相同的 cookie

Cookie 可以设置多个变量。通过使用不匹配的参数设置相同的 cookie,您将创建您的服务器端框架可能无法处理的重复项,或者默认为发送到服务器的第一个或最后一个。


Cookie 参数

域必须设置为当前域或父域。

路径

除了域层次结构之外,还有一个基本路径层次结构。默认值通常是“/”,使 cookie 可用于域内的所有路径。

HTTP-ONLY 标志

设置后,您将无法通过 JavaScript 修改所述 cookie,如果是这种情况,您很可能设置了重复的 cookie。

到期

这不会影响重复项,但如果设置为无效值,或者距离不够远(同一秒)的内容可能会被忽略或创建意外的 cookie。


建议

  • 确认为相关 cookie 设置的域和路径。
  • 使用一个固定的、已知的旧日期 (new Date(0).toGMTString()) 而不是从当前 date/time
  • 调整
  • 确保您设置的值为空,从 null/undefined 转换可能会导致意外的字符串。
  • 使用 location.replace('newurl') 而不是分配 location.href 以避免任何潜在的缓存问题。

在大多数情况下,以下内容应该会清除您的 cookie...

document.cookie = 'YOURKEY=; expires=THU, 01 JAN 1970 00:00:00 GMT';

如果您需要清理路径...

document.cookie = 'YOURKEY=; expires=THU, 01 JAN 1970 00:00:00 GMT; path=/';

放在一边

一般来说,不要将 cookie 设置得太远...