2010-10-29 106 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

相關問題