无法使用 AngularJS 的 $cookies 删除 cookie
Posted
技术标签:
【中文标题】无法使用 AngularJS 的 $cookies 删除 cookie【英文标题】:Can't delete cookie with AngularJS's $cookies 【发布时间】:2012-12-21 04:46:16 【问题描述】:我的网络应用程序是这样的,当用户登录服务器时,会在响应中添加一个 Set-Cookie 标头,如下所示:
Set-Cookie:JSESSIONID=1; Path=/myApp/; Secure
在注销时,我尝试在客户端(浏览器)上删除此 cookie,因为只要删除 cookie,我就不会关心会话是否在服务器上成功销毁。任何挥之不去的“幽灵”会话都会在服务器上不时清理。
但是,我的应用无法删除 JSESSIONID cookie。假设从https://test.myserver.com/myApp/app/index.html#/mySubPage
调用了注销函数,而注销函数确实如此:
delete $cookies["JSESSIONID"];
$location.path("/login");
cookie 没有被删除。刷新 Chrome 开发者工具中“资源”选项卡中的 cookie 列表显示它仍然存在。重新加载登录页面并刷新“资源”选项卡中列出的 cookie 仍然会显示 cookie。
为什么我不能从我的 javascript 客户端删除不是 HTTPOnly cookie 的 cookie?是导致问题的路径吗?不应该,因为脚本在 cookie 路径中包含的页面上运行。通常处理 Cookie 并没有那么难,所以我很清楚我在这里可能忽略了一些微不足道的事情 - 但任何帮助将不胜感激。
更新:
我在原始帖子中提供了错误的应用程序路径。它现在被编辑以反映正确的路径(嗯,抽象地)。事实证明,这是该问题的关键信息。 AngularJS 使用应用程序的完整相对路径作为它创建/删除的所有 cookie 的路径属性,因此由于我们的服务器将 cookie 设置为 /myApp/
的路径,并且应用程序在 /myApp/app
的相对路径上运行,Angular试图删除以前不存在的 cookie(为了覆盖或删除现有 cookie,名称、域和路径都需要与创建 cookie 时使用的相同)。
【问题讨论】:
您的模块中是否包含 ngCookies?像 angular.module('myApp', ['ngCookies']) 是的。我可以毫无问题地读取cookie。我在任何地方都没有收到任何错误,即使它应该被删除,cookie 仍然保持不变。 你试过 $cookieStore.remove(key) 吗? 另外一件事,$scope.digest() 发生了吗?是什么触发了 cookie 删除?如果它来自外部角度,则必须使用 $scope.$apply() 来启动手表。如果您正在调试(Chrome/Firebug),请在 angular-cookies.js 的 push() 函数中设置断点(最好使用非缩小版)。 不久前遇到了完全相同的问题。似乎 $.cookies 只能访问它自己设置的 cookie。我的解决方案是设置相同的 cookie 路径并在 Angular 应用程序之外使用 jQuery cookie 清除它们。 【参考方案1】:我想您应该检查来自服务器的响应 - 也许它们包含一个设置 cookie 值的“set cookie”标头字段。
这是一个Plunker example,它说明了如何添加/更改/删除/监视 cookie 的值(但没有可以更改 cookie 值的服务器端响应)。
但通常,$cookies 对象是一种“代理对象”,由 AngularJS ngCookies 模块双向跟踪,并且在浏览器的 cookie 更改时从一侧更改其字段(因此您可以 $watch 更改)但也会更改反映到浏览器的真实cookies,所以你可以改变这个对象。
所以cookie不能被删除的唯一原因是你在浏览器上删除它们,服务器再次设置cookie,重新加载页面后它仍然存在。
【讨论】:
我已经检查了服务器的响应,它没有附加 cookie :( +1 提供了使用 $cookie 服务的良好解释和良好示例。但是,它并没有为我解决问题,因此我无法将其标记为已接受的答案。但是,您无法回答问题是我自己的错,因为我在写问题时犯了一个重大错误(错误的应用程序路径)。我已经用正确的路径更新了问题,并解释了问题所在。【参考方案2】:注意您要删除的 cookie 的 cookie 域。如果您正在使用多个子域(即一个用于静态资源,另一个用于 api),您的问题可能是您尝试删除错误域的 cookie。
使用您选择的浏览器开发工具查看您的 cookie。为您遇到问题的要删除的 cookie 设置什么域,请在 remove 方法的 options 参数中指定它。
$cookies.remove('JSESSIONID', domain: 'domain.tld');
安全提示:通过 Javascript 删除会话 ID 不会删除服务器上的会话。如果您的会话 ID 泄漏,您可能会遭受会话固定的困扰。最好通过调用 API 中的注销端点来删除 cookie,这将完全清除服务器上的会话,使其无法重复使用。
【讨论】:
像 OP 一样,我的问题是路径,而不是域,但在选项中设置路径最终为我摆脱了 cookie。这是为我指明正确方向的答案。 我尝试了很多解决方案,但这是唯一让我满意的解决方案:删除 cookie 时设置路径和域:$cookies.remove("sessionId", path: "/",域:“mydomain.fr”);【参考方案3】:您在更新中给出的答案似乎是正确的:Angular $cookieStore
只能对路径值与当前路径相同的 cookie 起作用。
欺骗它的方法是使用 ajspera 在this issue 上给出的解决方案:
<head>
<base href="/">
</head>
只需将 <base href="/">
添加到 HTML 的 head 元素中,然后它就可以工作了。
另一种解决方案是使用发送它的服务器设置 cookie 的路径。在 Node.js Express 中看起来像
res.cookie('specialCookie', 'special!', path: '/myApp');
请注意,对我来说,$cookieStore 似乎去掉了尾部斜杠,因此您可能需要两种方式都尝试。
【讨论】:
感谢您实际提供有关如何解决此问题的说明。我得到了基本的 href 方法,但我认为可能有undesirable consequences,所以我更愿意从服务器设置路径......但我似乎无法弄清楚“/myApp”的值在哪里应该来自。我在 localhost:8080/mypage.html 上运行,参数为 angular.module 'theApp'。但是将路径设置为 ''、/theApp 或 /theApp/ 都会导致 Angular 无法访问 cookie。 "/myApp" 是您发送的 cookie 的路径选项。在您的情况下,您应该使用“/mypage.html”。或者,您可以尝试无路径选项(默认为请求 URL 的路径)或“/mypage”。 但我希望 cookie 可用于我网站的所有页面。有什么办法吗?在原发帖人的问题中,他有site/myapp/app/index.html#topic,但在解决方案中只引用了myapp/app。以上是关于无法使用 AngularJS 的 $cookies 删除 cookie的主要内容,如果未能解决你的问题,请参考以下文章
Angularjs总结$ cookie和$rootscope