2010-10-29 245 views
60

说,例如,我有一个应用程序发送以下HTTP标头设置为名为“一个” cookie:如何处理具有相同名称的多个Cookie?

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

如果我的服务器两条路径都有效的访问/example,所以我有两个名为饼干“一“!由于浏览器不发送任何路径信息,因此无法区分这两个Cookie。

Cookie: a=2; a=1 

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

+0

我会尽我所能(阅读:我可以做的每件事)以避免重复的cookie名称。大多数人从未遇到过这个问题 - 理由很充分。 – 2010-10-29 22:27:16

回答

31

this article on SitePoint

如果具有相同名称的多个cookie匹配给定的请求URI中,一个由浏览器选择的。

路径越具体,优先级越高。但是,基于其他属性(包括域)的优先级未指定,并且可能因浏览器而异。这意味着如果您已经为“.example.org”和“www.example.org”设置了相同名称的Cookie,则无法确定哪一个会被发回。

编辑:从2010年这个信息似乎已经过时,似乎浏览器可以在现在的回报低于@Nate发送多个cookie,看到答案细节

+6

那么如何删除多个相同的cookies?我已经打了两天了,而且重复的饼干似乎是坚不可摧的。 – 2012-08-07 23:14:51

+9

@Brant这篇文章可能会有些不正确 - 我刚刚看到Chrome发回了两个同名(但路径不同)的cookie,所以“一个由浏览器选择”不一定是真的。最深的路径cookie首先发送,BTW,这似乎是合理的。另外一块饼干也是在它们之间制作的。 – 2012-08-31 23:22:30

+0

哎呀,我的意思是@Jan,我猜。 – 2012-09-01 00:10:55

-1

如果你需要区分他们,你必须给他们不同的关键值。

0

我当然知道应用程序广泛使用多个会话标识来执行此操作,而且似乎一直运行。然而,我不知道 - 也无意发现 - 如果他们这样做,因为浏览器以一致的顺序返回cookie,这取决于它们的设置时间/设置的路径或应用程序是否尝试匹配一个到现有会话。

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

但是,如果你真的想知道浏览器(和应用程序)如何处理这种情况,为什么不建立一个测试装备并试用它。

+2

服务器无法控制浏览器发送给它的内容。它仍然需要处理。 – 2011-05-11 17:16:18

0

有没有错有对多个值同名......如果你想要他们。你甚至可以在值中嵌入额外的上下文。

如果你不这样做,那么当然如果你想要两个上下文,不同的名字是一个解决方案。

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

既然你知道最重要的部分(他们是如何工作的),并且你可以用几种不同的方式完成你所需要的部分,我对你的问题的回答是:这是一个开发人员问题。

59

提到SitePoint文章的答案并不完全完整。请参阅RFC 6265(公平地说,这个RFC是在发布这个问题后于2011年发布的,它取代了之前的2000年的RFC 2965和1997年的RFC 2109)。

第5节。4条第2款有这样一段话:

用户代理应该排序的cookie的列表按以下顺序:

  • 与路径较长饼干用更短的路径饼干之前上市。

注:并非所有的用户代理进行排序的cookie的列表顺序,但这 顺序反映在本文撰写常见的做法,而且, 历史上,已经有服务器的(错误地)取决于 这个命令。

也有在4.2.2节这个小宝石:

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

在您的示例请求的cookie(曲奇:A = 2; A = 1)注意,cookie中设置与路径/示例A = 2)具有长于一个路径与路径/a = 1),所以它会首先发送给您,符合规范的建议。因此,你或多或少正确的假设你可以选择的第一个值。

不幸的是RFC中所使用的语言是非常具体 - 使用的话SHOULD不应该 RFC中引入歧义。这些表示约定应遵循,但不要求要求符合规范。尽管我很了解RFC,但我还没有做过研究,看看真实世界的客户端在做什么;可能有一个或多个浏览器或其他软件充当HTTP客户端,可能不会首先在Cookie中发送最长路径cookie(例如:/example),其中包括标头。

如果你是在一个位置来控制cookie的值,你想使你的解决方案万无一失,你最好把两种:

  1. 使用不同的cookie名在某些路径覆盖

    ,如:

    • 的Set-Cookie:一个全局= 1;路径= /;版本= 1
    • 的Set-Cookie:一个-示例= 2;路径= /例子;版本= 1
  2. 存储你在cookie值本身需要的路径:

    • 的Set-Cookie:A = 1条&路径= /;路径= /;版本= 1
    • 的Set-Cookie:A = 2 &路径= /例子;路径= /例子;版本= 1

这两种解决方法需要在服务器上额外的逻辑来挑选期望的Cookie值,由所请求的URL针对可用的饼干的列表进行比较。这不太漂亮。不幸的是,RFC没有先见之明要求更长的路径完全覆盖具有较短路径的cookie(例如:在您的示例中,您将收到Cookie:a = 2只有)。

+1

谢谢你从这些该死的RFC中挖掘出来! //为什么如果没有人遵循这些建议,他们甚至都会读它们? – Rast 2014-09-03 07:00:44

+3

它看起来像Wildfly 8.0注意到cookie的顺序并使用第一个。这使我们可以在“嵌套”上下文中运行另一个应用程序。但是,如果某些浏览器不遵循RFC的建议,则会失败。正确的方法来设置会话cookie的不同名称,如JSESSIONID2。 – honzajde 2015-01-21 12:44:53

+0

在阅读完您的答案之后,我测试了主流浏览器:Chrome 63/Opera 55/IE11/Edge 16/Safari 11/Firefox 58他们都似乎正确地处理了这个问题,即较长路径的Cookie在较短路径之前。在PHP中(在版本7上测试),它只读取设置为$ _COOKIE变量的第一个cookie。 – 2018-02-12 18:56:16

相关问题