删除 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
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 设置得太远...