245

我一定错过了一些关于 cookie 的基本知识。在 localhost 上,当我在服务器端设置 cookie并将域明确指定为 localhost(或 .localhost)时。某些浏览器似乎不接受 cookie。

Firefox 3.5:我在 Firebug 中检查了 HTTP 请求。我看到的是:

Set-Cookie:
    name=value;
    domain=localhost;
    expires=Thu, 16-Jul-2009 21:25:05 GMT;
    path=/

或(当我将域设置为 .localhost 时):

Set-Cookie:
    name=value;
    domain=.localhost;
    expires=Thu, 16-Jul-2009 21:25:05 GMT;
    path=/

在任何一种情况下,都不会存储 cookie。

IE8:我没有使用任何额外的工具,但 cookie 似乎也没有被存储,因为它没有在后续请求中被发回。

Opera 9.64: localhost 和 .localhost 都可以工作,但是当我检查 Preferences 中的 cookie 列表时,域设置为 localhost.local,即使它列在 localhost 下(在列表分组中)。

Safari 4: localhost 和 .localhost 都可以工作,但它们总是在 Preferences 中列为 .localhost。另一方面,没有显式域的 cookie,它仅显示为 localhost(无点)。

本地主机有什么问题?由于存在如此多的不一致,因此必须有一些涉及 localhost 的特殊规则。此外,我并不完全清楚为什么域必须以点为前缀?RFC 2109 明确指出:

Domain 属性的值不包含嵌入的点或不以点开头。

为什么?该文件表明它必须做一些与安全有关的事情。我不得不承认我没有阅读完整的规范(以后可能会这样做),但这听起来有点奇怪。基于此,在 localhost 上设置 cookie 是不可能的。

4

23 回答 23

286

根据设计,域名必须至少有两个点;否则浏览器会认为它们无效。(参见http://curl.haxx.se/rfc/cookie_spec.html上的参考资料)

工作时,必须完全省略localhostcookie 域。您不应将其设置为or或代替. 那还不够。""NULLFALSE"localhost"

对于 PHP,请参阅http://php.net/manual/en/function.setcookie.php#73107上的评论。

如果使用 Java Servlet API,则根本不要调用该cookie.setDomain("...")方法。

于 2009-07-27T13:24:55.390 回答
43

我大致同意@Ralph Buchfelder,但这里有一些放大,通过尝试在我的本地计算机上复制具有多个子域(例如 example.com、fr.example.com、de.example.com)的系统时进行实验( OS X / Apache / Chrome|Firefox)。

我编辑了 /etc/hosts 以将一些虚构的子域指向 127.0.0.1:

127.0.0.1 localexample.com
127.0.0.1 fr.localexample.com
127.0.0.1 de.localexample.com

如果我正在处理 fr.localexample.com 并且我将域参数排除在外,则 cookie 会为 fr.localexample.com 正确存储,但在其他子域中不可见。

如果我使用“.localexample.com”域,则 cookie 会为 fr.localexample.com 正确存储,并且在其他子域中可见。

如果我使用“localexample.com”域,或者当我尝试使用“localexample”或“localhost”域时,cookie 不会被存储。

如果我使用“fr.localexample.com”或“.fr.localexample.com”域,则 cookie 会为 fr.localexample.com 正确存储,并且(正确地)在其他子域中不可见。

因此,在域中至少需要两个点的要求似乎是正确的,尽管我不明白为什么应该这样。

如果有人想尝试一下,这里有一些有用的代码:

<html>
<head>
<title>
Testing cookies
</title>
</head>
<body>
<?php
header('HTTP/1.0 200');
$domain = 'fr.localexample.com';    // Change this to the domain you want to test.
if (!empty($_GET['v'])) {
    $val = $_GET['v'];
    print "Setting cookie to $val<br/>";
    setcookie("mycookie", $val, time() + 48 * 3600, '/', $domain);
}
print "<pre>";
print "Cookie:<br/>";
var_dump($_COOKIE);
print "Server:<br/>";
var_dump($_SERVER);
print "</pre>";
?>
</body>
</html>
于 2013-05-20T14:58:35.053 回答
39

localhost:您可以使用:domain: ".app.localhost"它会起作用。'domain' 参数在域名中需要 1 个或多个点来设置 cookie。然后,您可以让会话跨 localhost 子域工作,例如:api.app.localhost:3000.

于 2014-02-27T13:45:32.387 回答
20

当 cookie 设置为显式域“localhost”时,如下所示...

设置 Cookie:名称=值; 域=本地主机;到期=格林威治标准时间 2009 年 7 月 16 日星期四 21:25:05;路径=/

...然后浏览器会忽略它,因为它不包含至少两个句点,并且不是七个经过特殊处理的顶级域之一

...域中必须至少有两 (2) 或三 (3) 个句点,以防止以下形式的域:“.com”、“.edu”和“va.us”。在下面列出的七个特殊顶级域之一中失败的任何域只需要两个句点。任何其他域至少需要三个。七个特殊的顶级域是:“COM”、“EDU”、“NET”、“ORG”、“GOV”、“MIL”和“INT”。

请注意,上述期间的数量可能假设需要前导期间。然而,这个时期在现代浏览器中被忽略了,它可能应该读...

至少一 (1) 或两 (2) 个时期

请注意,域属性的默认值是生成 cookie 响应的服务器的主机名

因此,未为 localhost 设置 cookie 的解决方法是简单地不指定域属性并让浏览器使用默认值 - 这似乎与域属性中的显式值具有相同的约束。

于 2015-08-25T17:21:53.110 回答
11

如果您正在设置来自另一个域的 cookie(即,您通过发出 XHR 跨源请求来设置 cookie),那么您需要确保withCredentials在用于获取 cookie 的 XMLHttpRequest 上将属性设置为 true,如此处所述

于 2019-01-23T11:40:43.113 回答
4

结果因浏览器而异。

Chrome- 127.0.0.1 工作但 localhost .localhost 和 "" 没有。Firefox- .localhost 有效,但 localhost、127.0.0.1 和 "" 没有。

未在 Opera、IE 或 Safari 中测试过

于 2012-08-23T13:17:15.983 回答
4

我自己花了很多时间来解决这个问题。

使用 PHP,这个页面上没有任何东西对我有用。我最终在我的代码中意识到PHP 的 session_set_cookie_params()的“安全”参数总是设置为 TRUE。

由于我没有使用 https 访问本地主机,因此我的浏览器永远不会接受 cookie。因此,我修改了我的那部分代码,以根据 $_SERVER['HTTP_HOST'] 是否为 'localhost' 有条件地设置 'secure' 参数。现在工作得很好。

我希望这可以帮助别人。

于 2016-12-15T09:16:06.503 回答
3

使用 127.0.0.1 作为域进行本地测试时,我的运气要好得多。我不知道为什么,但我对 localhost 和 .localhost 等的结果好坏参半。

于 2012-04-01T18:28:51.517 回答
3

我这样解决的跨站点cookie问题:

后端

服务器端

  • 服务于:http://localhost:8080
  • 创建响应时,设置 Cookie

属性:

SameSite=None; Secure; Path=/

客户端

前端(在我的例子中是 Angular)

  • 服务于:http://localhost:4200/
  • 向服务器(后端)发送请求时

设置 XHR.withCredentials=true:

var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://localhost:8080/', true);
xhr.withCredentials = true;
xhr.send(null);

我的解释:

  • 后端和前端域不同时,是否将cookie保存在前端域cookie存储中的决定是由浏览器带来的接收响应。withCredentials=true仅当 XHR 请求具有并且收到正确的服务器 Cookie 属性(HTTP Set-Cookie 标头)时,浏览器才允许发送 cookie

  • 当后端和前端域不同时,由浏览器决定是否在请求中发送 cookie 。仅当 XHR 请求具有withCredentials=true

  • 换句话说,如果省略 - cookiewithCredentials=true不会在请求中发送,也不会从响应中接收和保存

  • 收到的 cookie 总是存储在浏览器 cookie 存储中的前端域名下。如果服务器域不同并且cookies保存成功,效果与前端域首先发送的效果相同。

  • 如果SameSite=None省略 cookie 属性,今天的浏览器 (Firefox/Chrome) 将使用默认Lax模式,这对于跨站点 cookie 来说过于严格

  • 如果Securedcookie 属性被省略 - 那么SameSite=None将被忽略 - 它需要Secured被设置

  • 对于 localhost Securedcookie 属性浏览器不需要 HTTPS / SSL,http将工作 - 无需在https://localhost ... EDIT 2022-03-02下提供前端或后端- 对于 Safari (v15.1) 这不是真的 -> 在 Safari http:// localhost + cookie with Secure - cookie 将被忽略,不会保存在浏览器中(解决方案:对于 Safari + http://localhost 删除 Secure 和 SameSite,如果提供)。

诊断提示:

  • 为了检查 cookie 是否已发送 - 打开浏览器开发人员工具并检查网络选项卡。找到后端的请求并检查标头 - 在请求标头中搜索 Cookie 标头,在响应标头中搜索 Set-Cookie
  • 为了检查 cookie 是否被保存 - 打开浏览器开发工具,查看存储管理器 (Firefox),检查 Cookie 并搜索前端域名,检查 cookie 是否存在,如果存在,检查它的创建时间......
  • 不要忘记先在后端设置 CORS

参考:https ://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie

于 2021-12-09T15:51:43.510 回答
3

您可以使用,localhost.org或者更确切地说.localhost.org,它总是会解决127.0.0.1

于 2019-03-27T19:40:43.603 回答
3

唯一对我有用的是设置Path=/在 cookie 上。

此外,路径属性的默认值似乎因浏览器而异,尽管我只测试了其中两个(Firefox 和 Chrome)。

Chrome 尝试按原样设置 cookie;如果标题path中省略了属性,Set-Cookie那么它将不会被存储和忽略。

然而,即使没有明确的path属性,Firefox 也会存储一个 cookie。它只是用请求的路径设置它;我的请求网址是/api/v1/users并且路径设置为/api/v1自动。

无论如何,当path设置为/即使没有明确的域(即Domain=localhost或其他东西)时,两个浏览器都可以工作。因此,每个浏览器处理 cookie 的方式存在一些差异。

于 2019-11-24T02:36:51.160 回答
2

没有任何建议的修复对我有用 - 将其设置为 null、false、添加两个点等 - 不起作用。

最后,我只是从 cookie 中删除了域,如果它是 localhost 并且现在在Chrome 38中对我有用。

以前的代码(不起作用):

document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';

新代码(现在工作):

 if(document.domain === 'localhost') {
        document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';path=/;' ;
    } else {
        document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';
    }
于 2014-11-05T03:42:09.470 回答
2

https://<local-domain>使用then时似乎有问题http://<local-domain>。在站点设置它们http://之后,站点不会发送带有请求的 cookie 。https://强制重新加载和清除缓存没有帮助。只有手动清除 cookie 有效。此外,如果我在页面上清除它们https://,那么http://页面将再次开始工作。

看起来与“严格的安全 cookie”有关。很好的解释在这里。它于2017 年 4 月 19日在 Chrome 58中发布。

看起来 Chrome 实际上确实记录了安全 cookie 和非安全 cookie,因为它会在单击地址栏图标时根据页面的协议显示正确的 cookie。

但是Developer tools > Application > Cookies当同一个域有同名的安全cookie时不会显示非安全cookie,也不会随任何请求发送非安全cookie。这似乎是一个 Chrome 错误,或者如果这种行为是预期的,则应该有某种方法可以在http页面上查看安全 cookie 并指示它们被覆盖。

解决方法是根据它们是用于 http 站点还是 https 站点来使用不同的命名 cookie,并将它们命名为特定于您的应用程序。前缀表示 cookie 应该是严格安全的__Secure-,这也是一个很好的做法,因为安全和非安全不会冲突。前缀还有其他好处。

/etc/hosts对 https 和 http 访问使用不同的域也可以,但是一次意外https://localhost访问会阻止任何同名的 cookie 在http://localhost站点上工作 - 所以这不是一个好的解决方法。

我已经提交了一份Chrome 错误报告

于 2018-05-14T14:19:30.163 回答
2

经过大量实验和阅读各种帖子后,这行得通。我可以设置多个 cookie,将它们读回并将时间设置为负数并删除它们。

func addCookie(w http.ResponseWriter, name string, value string) {
    expire := time.Now().AddDate(0, 0, 1)
    cookie := http.Cookie{
       Name:    name,
       Value:   value,
       Expires: expire,
       Domain:  ".localhost",
       Path:    "/",
    }
    http.SetCookie(w, &cookie)
}
于 2019-11-07T19:44:56.620 回答
1

尝试了上述所有选项。对我有用的是:

  1. 确保对服务器的请求将withCredentials设置为 true。来自不同域的 XMLHttpRequest 无法为其自己的域设置 cookie 值,除非在发出请求之前将 withCredentials 设置为 true。
  2. 不要设置Domain
  3. Path=/

结果Set-Cookie标题:

Set-Cookie: session_token=74528588-7c48-4546-a3ae-4326e22449e5; Expires=Sun, 16 Aug 2020 04:40:42 GMT; Path=/
于 2020-08-16T21:41:10.203 回答
1

Chromium open 自 2011 以来存在一个问题,如果您明确将域设置为“localhost”,则应将其设置为falseor undefined

于 2015-07-14T20:58:55.133 回答
1

Cookie 需要指定SameSite属性,None值过去是默认值,但最近的浏览器版本Lax将默认值设为对某些类别的跨站请求伪造 (CSRF) 攻击具有相当强大的防御能力。

SameSite=Lax您一起也应该有Domain=localhost,因此您的 cookie 将被关联localhost并保存。它应该看起来像这样:

document.cookie = `${name}=${value}${expires}; Path=/; Domain=localhost; SameSite=Lax`;

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite

于 2020-09-19T04:59:21.083 回答
1

我遇到了同样的问题,我通过在 cookie 名称本身中添加 2 个点而不指定任何域来修复它。

set-cookie: name.s1.s2=value; path=/; expires=Sun, 12 Aug 2018 14:28:43 GMT; HttpOnly
于 2018-01-24T15:22:36.887 回答
0

另一个重要的细节是expires=应该使用以下日期时间格式:Wdy, DD-Mon-YYYY HH:MM:SS GMT ( RFC6265 - Section 4.1.1 )。

Set-Cookie:
  name=value;
  domain=localhost;
  expires=Thu, 16-07-2019 21:25:05 GMT;
  path=/
于 2011-06-15T05:15:26.553 回答
0

document.cookie = valuename + "=" + value + "; " + expires + ";domain=;path=/";

这个“域=;路径=/”;将采用动态域,因为它的 cookie 将在子域中工作。如果您想在 localhost 中进行测试,它将起作用

于 2014-10-07T09:35:15.483 回答
0

这里没有一个答案对我有用。我通过将我的 PHP 作为页面中的第一件事来修复它。

与其他标头一样,必须在脚本的任何输出之前发送 cookie(这是协议限制)。这要求您在任何输出之前调用此函数,包括和标记以及任何空格。

来自http://php.net/manual/en/function.setcookie.php

于 2015-01-09T23:29:59.500 回答
0

我有一个类似的问题,我的后端和前端在本地主机上运行,​​但端口不同。为了解决这个问题,我在我的请求选项中省略了DomainSet-Cookie使用。withCredentials: true

这里

于 2021-10-11T07:31:23.180 回答
0

我玩了一下。

Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=localhost; Path=/

从今天开始在 Firefox 和 Chrome 中运行。但是,我没有找到使它与 curl 一起使用的方法。我尝试了 Host-Header 和 --resolve,没有运气,任何帮助表示赞赏。

但是,如果我将其设置为,它可以在 curl 中使用

Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=127.0.0.1; Path=/

反而。(这不适用于 Firefox。)

于 2017-01-30T21:41:48.647 回答