如何处理多个同名Cookie?


92

举例来说,我有一个应用程序发送以下HTTP标头以设置为名为“ a”的cookie:

Set-Cookie: a=1;Path=/;Version=1
Set-Cookie: a=2;Path=/example;Version=1

如果我/example在服务器上访问,则两个路径均有效,因此我有两个名为“ a”的cookie!由于浏览器不发送任何路径信息,因此无法区分两个cookie。

Cookie: a=2; a=1

这种情况应该如何处理?选择第一个?创建具有所有cookie值的列表?还是应该将这种情况视为开发人员的错误?


我将尽我所能(请阅读:力所能及的)以避免重复的cookie名称。大多数人从未遇到过这个问题-这是有充分理由的。

网站只能读取自己的cookie。它无法读取其他网站/域的cookie。浏览器确保了这种安全性。这可能是给绝对初学者的提示(我有些困惑)
Arun

Answers:


38

SitePoint上的这篇文章中

如果多个同名的Cookie匹配给定的请求URI,则浏览器将选择一个。

路径越具体,优先级越高。但是,基于其他属性(包括域)的优先级未指定,并且在浏览器之间可能会有所不同。这意味着,如果您在“ .example.org”和“ www.example.org”上设置了相同名称的cookie,则无法确定哪个cookie将被发回。

编辑:2010年的此信息似乎已过时,似乎浏览器现在可以发送多个cookie作为回报,有关详细信息,请参见下面@Nate的答案


8
那么,如何删除多个相同的Cookie?我已经为此进行了两天的尝试,重复的cookie似乎坚不可摧。
鲍勃·琼斯

13
@Brant这篇文章可能有点不正确-我刚刚看到Chrome发送了两个同名(但路径不同)的Cookie,因此“浏览器选择了一个”不一定正确。最深的路径cookie首先发送,BTW,这似乎是合理的。另一个cookie也使它介于两者之间。
乔纳斯N

3
Firefox(15)还会发送两个具有相同名称的cookie!如果它遇到两个用于域.a.com和主机的cookiea.com
Taha Jahangir 2012年

确实,此信息是错误的。@Nate的答案应该标记为正确。
丹·米隆

4
404:找不到著名的@Nate的答案。
d.popov

90

指向SitePoint上一篇文章的答案并不完整。请参阅RFC 6265(为公平起见,此问题发布后,该RFC于2011年发布,它取代了2000年的RFC 2965和1997年的RFC 2109)。

5.4节第2小节说:

用户代理应按以下顺序对Cookie列表进行排序:

  • 路径较长的Cookie会在路径较短的Cookie之前列出。

注意:并非所有用户代理都按此顺序对cookie列表进行排序,但是此顺序反映了编写本文档时的惯例,并且从历史上看,有(错误地)依赖此顺序的服务器。

4.2.2节中也有这个小宝石:

...服务器不应该依赖序列化顺序。特别是,如果Cookie标头包含两个具有相同名称的Cookie(例如,使用不同的Path或Domain属性设置的Cookie),则服务器不应依赖于这些Cookie在标头中出现的顺序。

在您的示例请求cookie(Cookie:a = 2; a = 1)中,请注意,设置为/ examplea = 2)的cookie的路径比设置为/a = 1)的cookie的路径更长,因此它会首先按照规范的要求发送回给您。因此,您可以选择第一个值的假设或多或少是正确的。

不幸的是,RFC中使用的语言是非常特定的-使用单词应该不应在RFC中引入歧义。这些指示遵循的约定,但并非必须符合规范。尽管我对RFC非常了解,但我还没有进行研究来了解实际客户的工作。可能有一个或多个充当HTTP客户端的浏览器或其他软件可能未先在Cookie:标头中发送最长路径cookie(例如:/ example)。

如果您可以控制cookie的值并且希望使解决方案变得万无一失,则最好采用以下两种方法:

  1. 使用不同的Cookie名称覆盖某些路径,例如:

    • 设置cookie:a-global = 1; Path = /; Version = 1
    • 设置cookie:a-example = 2; Path = / example; Version = 1
  2. 将所需的路径存储在cookie值本身中:

    • 设置cookie:a = 1&path = /; Path = /; Version = 1
    • 设置cookie:a = 2&pat​​h = / example; Path = / example; Version = 1

通过将请求的URL与可用cookie列表进行比较,这两种解决方法都需要服务器上的其他逻辑来选择所需的cookie值。不太漂亮 不幸的是,RFC没有先见之明,要求较长的路径完全覆盖具有较短路径的cookie(例如:在您的示例中,您将收到Cookie: a = 2)。


2
感谢您从这些该死的RFC中找出来!///如果没有人遵循这些建议,为什么还要读这些书呢?..
2014年

3
看起来Wildfly 8.0正在注意cookie的顺序,并使用第一个cookie。这使我们可以在“嵌套”上下文中运行另一个应用程序。但是,如果某些浏览器不遵循RFC的建议,它将失败。正确的方法是设置会话Cookie的其他名称,例如JSESSIONID2。
honzajde 2015年

2
在阅读您的答案后,我确实测试了主要的浏览器:Chrome 63 / Opera 55 / IE11 / Edge 16 / Safari 11 / Firefox 58并且它们似乎都正确地处理了路径较长的Cookie在路径较短的Cookie之前。在PHP(已在版本7中进行测试)中,它仅读取设置为$ _COOKIE变量的第一个cookie。
亚历山大·史兰兹

1
path=/;Path=/规格是否符合FRC-6265?我没有发现这样的提及。 Tomcat威胁任何“;” 在路径中作为不正确的符号
Hubbitus

1
@Hubbitus注意,是a=2&path=/example;Path=/example这样的;,路径中没有。
富兰克林于

2

如果您想拥有多个相同名称的值,这没有错。您甚至可以在该值中嵌入其他上下文。

如果您不这样做,那么如果您想同时使用两个上下文,那么当然可以使用不同的名称。

另一种方法是即使来自更具体的路径也要使用相同的路径(和域)发送相同的cookie名称。这些设置的cookie指令将覆盖该cookie的值。

既然您知道了最重要的部分(它们如何工作),并且可以通过几种不同的方式完成所需的工作,那么我对您的问题的回答是:这是开发人员的问题。


0

我当然知道应用程序广泛使用多个会话ID来执行此操作-并且似乎能够始终如一地工作。但是我不知道-也不打算找出-是否这样做,因为浏览器以一致的顺序返回cookie,具体取决于设置它们的时间/设置的路径或应用程序是否尝试匹配每个cookie一个到现有会话。

我强烈建议避免这种做法。

但是,如果您真的想知道浏览器(和应用程序)如何处理这种情况,为什么不构建测试装备并进行尝试。


2
服务器无法控制浏览器发送给它的内容。仍然需要处理。
马丁·奥康纳

0

如果您使用Java / Scala框架播放:请当心!如果请求中包含多个同名Cookie,则Play只会向您的代码中显示其中一个。


-2

如果需要区分它们,则必须给它们提供不同的键值。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.