具有显式域的本地主机上的cookie

我一定是忽略了饼干的一些基本特性。在localhost上,当我在服务器端而且上设置cookie时,显式地将域指定为localhost(或.localhost)。有些浏览器似乎不接受cookie。

我检查了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 工作,但当我检查首选项中的cookie列表时,域被设置为localhost。Local,即使它列在localhost下(在列表分组中)。

Safari 4: localhost和.localhost都是工作,但它们总是在首选项中列出。localhost。另一方面,一个没有显式域的cookie,它只显示为localhost(没有点)。

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

Domain属性的值 不包含或不包含嵌入点

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

355187 次浏览

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

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

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

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

另一个重要的细节是,到期=应该使用以下日期时间格式: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>

你可以使用:domain: ".app.localhost",它将工作。域名中的“domain”参数需要1个或多个点用于设置cookie。然后你可以让会话跨本地主机子域工作,例如:api.app.localhost:3000

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

这个“域= < p >;路径= /”;将采用动态域作为其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年开始,如果你显式地将域设置为'localhost',你应该将它设置为falseundefined

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

< p > set - cookie: name =价值; 域= localhost < / >强;到期=周四,16- july 2009 21:25:05 GMT;路径= /

...那么浏览器会忽略它,因为它不包括至少两个时期,不是七个专门处理的顶级域名之一

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

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

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

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

所以没有为localhost设置cookie的解决方法是不指定域属性,并让浏览器使用默认值-这似乎没有相同的约束,一个显式的值在域属性。

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

使用PHP,这个页面上的任何东西都不适合我。我最终在我的代码中意识到PHP的session_set_cookie_params ()的“secure”参数总是被设置为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>时,似乎有一个问题。http://站点在https://站点设置cookie后不会随请求一起发送cookie。强制重载和清除缓存没有帮助。只有手动清除cookie才能工作。同样,如果我在https://页清除它们,那么http://页将重新开始工作。

看起来和"严格安全cookie "有关。好解释在这里。它是Chrome 58发布在2017-04-19。

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

但是Developer tools > Application > 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是;如果path属性在Set-Cookie头文件中被省略,那么它将不会被存储和忽略。

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

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

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

  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=/

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中省略了Domain,并在我的请求选项中使用withCredentials: 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);

我的解释:

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

  • 当后端和前端域不同时 决定是否在请求内发送cookie是浏览器带来的。浏览器只允许XHR请求有withCredentials=true

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

  • 接收到的cookie在浏览器cookie存储中总是存储在前端域名下。如果服务器域不同,cookie保存成功,效果就像从前端域发送一样。

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

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

  • 对于本地主机Secured cookie属性浏览器不需要HTTPS / SSL, http将工作-不需要在https://localhost ...下服务前端或后端编辑2022-03-02 -对于Safari (v15.1)这是不正确的->在Safari http://localhost + cookie with Secure - cookie将被忽略,而不是保存在浏览器中(解决方案:对于Safari + http://localhost删除Secure和SameSite如果提供)。

诊断提示:

  • 为了检查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和withCredentials: true,但这是失败的。将请求切换到get并更改后端以匹配工作。