我一定是忽略了饼干的一些基本特性。在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是不可能的。
我解决的跨站点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
我解决的跨站点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
当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的解决方法是简单地不指定域属性,并让浏览器使用默认值-这似乎没有域属性中的显式值所具有的相同约束。