我一定是忽略了饼干的一些基本特性。在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都可以工作,但它们总是在首选项中列出为.localhost。另一方面,一个没有显式域的cookie,它只显示为localhost(没有点)。

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

Domain属性的值 不包含或不包含嵌入点 从一个点开始。

为什么?该文档表明它必须在安全性方面做一些事情。我必须承认我没有阅读完整的规范(可能以后会读),但它听起来有点奇怪。基于此,在本地主机上设置cookie是不可能的。


按照设计,域名必须至少有两个点;否则浏览器将认为它们无效。(详见http://curl.haxx.se/rfc/cookie_spec.html)

在localhost上工作时,必须完全省略cookie域。你不应该将它设置为""或NULL或FALSE而不是"localhost"。这还不够。

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

如果使用Java Servlet API,完全不要调用cookie.setDomain("…")方法。


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

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

我在使用127.0.0.1作为域进行本地测试时运气要好得多。我不知道为什么,但我有混合的结果与localhost和.localhost等。


不同浏览器的结果也不同。

Chrome- 127.0.0.1工作,但localhost .localhost和“”不能。 Firefox- .localhost可以工作,但localhost、127.0.0.1和“”不能工作。

没有在Opera, IE或Safari中测试过


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

我编辑了/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上工作,并且去掉域参数,则为fr.localexample.com正确存储cookie,但在其他子域中不可见。

如果我使用“。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>

localhost:你可以使用:domain: ".app。Localhost”,它会工作。“domain”参数需要在域名中加上一个或多个点,用于设置cookie。然后你可以让会话跨localhost子域工作,比如:api.app.localhost:3000。


文档。Cookie = valuename + "=" + value + ";" + expires + ";域=;path=/";

这种“域=;路径= /”;将采用动态域作为其cookie将工作在子域。 如果你想在localhost测试,它会工作


所有建议的修复程序都不适合我——设置为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=/;';
    }

这里没有一个答案对我有用。我把我的PHP作为页面的第一件事来解决这个问题。

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

从http://php.net/manual/en/function.setcookie.php


在2011年开放的Chromium上有一个问题,如果你显式地将域设置为“localhost”,你应该将它设置为false或未定义。


当cookie设置为显式域'localhost'时,如下所示…

set - cookie: name =价值; 域=主机;到期=周四,16- july 2009 21:25:05 GMT;路径= /

...然后浏览器会忽略它,因为它不包括至少两个句点,也不是七个专门处理的顶级域之一。

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

请注意,上面的周期数可能假设需要一个前导周期。然而,在现代浏览器中,这个句点被忽略了,它应该读作…

至少一(1)或两(2)个句点

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

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


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

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

因为我没有用https访问localhost,我的浏览器永远不会接受cookie。所以,我修改了我的代码的那一部分,有条件地设置'安全'参数基于$_SERVER['HTTP_HOST']是'localhost'或不是。现在工作得很好。

我希望这能帮助到一些人。


我只是玩玩而已。

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

目前可以在Firefox和Chrome上运行。但是,我没有找到一种方法使它与卷曲一起工作。我试过Host-Header和——决心,没有运气,感谢任何帮助。

但是,如果我设置为,它在curl中工作

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

代替。(Firefox不支持这个功能。)


我也有同样的问题,我通过在cookie名称本身放置2个点而不指定任何域来修复它。

set-cookie: name.s1.s2=value; path=/; expires=Sun, 12 Aug 2018 14:28:43 GMT; HttpOnly

当您使用https://<local-domain>然后使用http://<local-domain>时,似乎有一个问题。https:// site设置cookie后,http:// site不会随请求一起发送cookie。强制重载和清除缓存没有帮助。只有手动清除cookie才能工作。同样,如果我在https://页面上清除它们,那么http://页面将重新开始工作。

看起来和"严格安全cookie "有关。解释得很好。它于2017-04-19在Chrome 58中发布。

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

但是开发工具>应用程序> Cookies将不会显示一个非安全cookie,当有一个安全cookie的相同名称的同一域,它也不会发送非安全cookie与任何请求。这似乎是一个Chrome错误,或者如果这种行为是预期的,应该有一些方法来查看安全cookie时,http页面和一个指示,他们正在被覆盖。

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

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

我已经提交了Chrome错误报告。


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


你可以使用localhost.org或。localhost.org,它总是会解析为127.0.0.1


经过多次试验和阅读各种帖子后,这是有效的。我可以设置多个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)
}

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

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

Chrome试图设置cookie是;如果路径属性在Set-Cookie头中被省略,那么它将不会被存储和忽略。

然而,Firefox即使没有显式的路径属性也可以存储cookie。它只是用请求的路径设置它;我的请求url是/api/v1/users,路径被自动设置为/api/v1。

不管怎样,当path被设置为/时,即使没有显式的域,即domain =localhost或其他东西,这两个浏览器都可以工作。因此,每种浏览器处理cookie的方式都有所不同。


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

确保对服务器的请求将withCredentials设置为true。来自不同域的XMLHttpRequest不能为自己的域设置cookie值,除非在发出请求之前将withCredentials设置为true。 不要设置域名 设置路径= /

结果Set-Cookie报头:

Set-Cookie: session_token=74528588-7c48-4546-a3ae-4326e22449e5; Expires=Sun, 16 Aug 2020 04:40:42 GMT; Path=/

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


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

在这里看到的


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

后端

服务器端

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

属性:

SameSite=None; Secure; Path=/

客户端

Frontend(在我的例子中是Angular)

服务网站:http://localhost:4200/ 当发送请求到服务器(后端)

设置XHR.withCredentials = true:

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

我的解释:

when backend and frontend domains differ the decision if the cookies will be saved in frontend domain cookie storage from received response is brought by the browser. Browser will allow sending cookies ONLY if XHR request has withCredentials=true and correct server Cookie attributes (HTTP Set-Cookie header) are recieved when backend and frontend domains differ the decision if the cookies will be sent within request is brought by the browser. Browser will allow this ONLY if XHR request has withCredentials=true in other words, if withCredentials=true is ommited - cookies won't be sent within request NOR will be recieved and saved from response recieved cookies are allways stored under frontend domain name in browser cookie storage. In case when server domain differs and cookies are saved successfully, the effect is the same as if they have been sent by frontend domain in the first place. if SameSite=None cookie attribute is omitted today's browser (Firefox/Chrome) will use default Lax mode which is too strict for cross site cookies if Secured cookie attribute is ommited - then SameSite=None will be ignored - it requires Secured to be set for localhost Secured cookie property browser does not require HTTPS / SSL, http will work - no need to serve frontend or backend under https://localhost ...

编辑2022-03-02 -对于Safari (v15.1),这是不正确的->在Safari http://localhost + cookie与安全- cookie将被忽略,而不是保存在浏览器中(解决方案:对于Safari + http://localhost删除Secure和SameSite如果提供)。

编辑2023-01-13 - @Barnaby报告说“Firefox拒绝设置它:'被拒绝,因为非https cookie不能被设置为'安全'。’”如果是这样的话,针对Safari的解决方案应该可以工作(见上面的EDIT 2022-03-02)。

诊断提示:

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

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


如果有人仍然面临这个问题,我发现从post请求切换到get请求是必要的。

我使用axios,并在前端使用凭据:true,但这是失败的。切换请求到get并更改后端以匹配工作。