Як обробляти кілька файлів cookie з однаковим ім'ям?


92

Скажімо, наприклад, у мене була програма, що надсилає такі заголовки HTTP для встановлення файлу cookie з назвою "a":

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

Якщо я отримую доступ /exampleдо сервера на обох шляхах, це означає, що у мене є два файли cookie з назвою "a"! Оскільки браузер не надсилає жодної інформації про шлях, два файли cookie не можна розрізнити.

Cookie: a=2; a=1

Як слід розглядати цю справу? Виберіть перший? Створити список із усіма значеннями файлів cookie? Або такий випадок слід розглядати як помилку розробника?


Я б зробив усе можливе (читай: усе, що можу), щоб уникнути дублювання назв файлів cookie. Більшість людей ніколи не стикалися з цим питанням - з поважної причини.

Веб-сайт може читати лише власні файли cookie. Він не може прочитати файли cookie іншого веб-сайту / домену. Цю безпеку забезпечує браузер. Це може бути підказкою для абсолютно початківців (у мене була ця плутанина)
Арун

Відповіді:


38

З цієї статті на SitePoint :

Якщо декілька файлів cookie з однаковим іменем відповідають даному URI запиту, браузер вибирає один із них.

Чим конкретніший шлях, тим вищий пріоритет. Однак пріоритет, який базується на інших атрибутах, включаючи домен, не вказаний і може відрізнятися у різних браузерах. Це означає, що якщо ви встановили однойменні файли cookie проти ".example.org" та "www.example.org", ви не можете бути впевнені, який із них буде повернено назад.

Редагувати: ця інформація за 2010 рік, здається, застаріла, схоже, браузери тепер можуть надіслати кілька кукі-файлів взамін, детальніше див. Відповідь @Nate нижче


8
Отже, як можна видалити кілька однакових файлів cookie? Я забивав це вже два дні, і дублікати файлів cookie здаються незнищенними.
Боб Джонс,

13
@Brant Ця стаття може бути дещо неправильною - я щойно бачив, як Chrome надсилає два файли cookie з однаковим іменем (але різними шляхами) назад, тому "один вибирає браузер" не обов'язково відповідає дійсності. Спочатку було надіслано файли cookie з найглибшим шляхом, до речі, що здається обґрунтованим. І ще одне печиво це зробило між ними.
Jonas N

3
Firefox (15) також надсилає два файли cookie з однаковим ім'ям! якщо він зіткнувся з двома файлами cookie для домену .a.comта хостаa.com
Таха Джахангір

Насправді ця інформація хибна. Відповідь @Nate слід позначити як правильну.
Dan Milon

4
404: Знаменитої відповіді @ Nate не знайдено.
d.popov

90

Відповідь на статтю про SitePoint є не зовсім повною. Будь ласка, дивіться RFC 6265 (для справедливості, цей RFC був випущений в 2011 році після публікації цього питання, який замінює попередні RFC 2965 від 2000 року та RFC 2109 від 1997 року).

У підрозділі 2 розділу 5.4 сказано:

Агент користувача СЛІД сортувати список файлів cookie в такому порядку:

  • Файли cookie з довшими контурами перераховані перед файлами cookie з коротшими контурами.

ПРИМІТКА: Не всі користувацькі агенти сортують список файлів cookie у цьому порядку, але цей порядок відображає загальну практику, коли цей документ був написаний, і, історично склалося, існували сервери, які (помилково) залежали від цього замовлення.

У розділі 4.2.2 також є ця маленька перлина :

... сервери НЕ ПОВИННІ покладатися на порядок серіалізації. Зокрема, якщо заголовок Cookie містить два файли cookie з однаковим іменем (наприклад, які були встановлені з різними атрибутами Шлях або Домен), сервери НЕ ПОВИННІ покладатися на порядок, у якому ці файли cookie відображаються в заголовку.

У вашому прикладі файлу cookie запиту ( Cookie: a = 2; a = 1 ) зауважте, що файл cookie, встановлений із шляхом / прикладом ( a = 2 ), має довший шлях, ніж той, що має шлях / ( a = 1 ), і тому відправляється вам першим у черзі, що відповідає рекомендаціям специфікації. Таким чином, ви більш-менш правильно вважаєте, що можете вибрати перше значення.

На жаль, мова, що використовується в RFC, надзвичайно специфічна - використання слів СЛІД та НЕ ПОВИННО вводити двозначність у RFC. Вони вказують на домовленості, яких слід дотримуватися, але не потрібно, щоб вони відповідали специфікації. Хоча я цілком добре розумію RFC для цього, я не проводив дослідження, щоб побачити, що роблять реальні клієнти; можливо, один або кілька браузерів або інших програмних засобів, що діють як клієнти HTTP, можуть не надіслати файл cookie з найдовшим шляхом (наприклад: / example ) першим у файлі cookie: заголовку

Якщо ви можете контролювати цінність файлів cookie і хочете зробити своє рішення надійним, вам найкраще:

  1. використання іншого імені файлу cookie для заміни в певних шляхах, таких як:

    • Set-cookie: a-global = 1; Шлях = /; Версія = 1
    • Set-cookie: a-example = 2; Шлях = / example; Версія = 1
  2. зберігання потрібного шляху у самому значенні файлу cookie:

    • Set-cookie: a = 1 & path = /; Path = /; Версія = 1
    • Set-cookie: a = 2 & path = / example; Path = / example; Версія = 1

Обидва ці обхідні шляхи вимагають додаткової логіки на сервері для вибору бажаного значення файлу cookie, порівнюючи запитану URL-адресу зі списком доступних файлів cookie. Це не надто красиво. Це сумно RFC , НЕ завбачливо вимагати , що довший шлях повністю перекриває печиво з більш коротким шляхом (наприклад , в вашому прикладі, ви отримаєте Cookie: а = 2 тільки ).


2
Дякуємо, що викопали це з цих проклятих RFC! // навіщо взагалі турбуватися їх читанням, якщо ніхто не дотримується цих рекомендацій? ..
Раст

3
Схоже, Wildfly 8.0 звертає увагу на порядок файлів cookie та використовує перший. Це дозволяє нам запускати інший додаток у вкладеному контексті. Однак це не вдасться, якщо деякі браузери не виконують рекомендації RFC. Правильний спосіб зробити це, щоб встановити іншу назву сеансового файлу cookie, наприклад JSESSIONID2.
honzajde

2
Я протестував основні браузери, прочитавши вашу відповідь: Chrome 63 / Opera 55 / IE11 / Edge 16 / Safari 11 / Firefox 58 І всі вони, здається, правильно справляються з тим, що Cookie з довшим шляхом передує тому, що має коротший шлях. А в PHP (протестовано у версії 7) він читає лише перший файл cookie, для якого встановлено змінну $ _COOKIE.
Alexander Schranz,

1
Чи path=/;Path=/відповідає специфікація FRC-6265? Я не знайшов такої згадки. Загроза Tomcat будь-яка ";" на шляху як неправильний символ
Hubbitus

1
@Hubbitus Зверніть увагу, це означає, a=2&path=/example;Path=/exampleщо немає ;шляху.
Франклін Ю

2

Немає нічого поганого в тому, що для одного і того ж імені існує кілька значень ... якщо ви їх хочете. Ви навіть можете вбудувати додатковий контекст у значення.

Якщо ви цього не зробите, тоді, звичайно, різні імена - це рішення, якщо ви хочете обидва контексти.

Альтернативою є надсилання одного і того ж імені файлу cookie з однаковим шляхом (і доменом) навіть із більш конкретних шляхів. Ці встановлені інструкції щодо файлів cookie замінять значення цього файлу cookie.

Тепер, коли ви знаєте найважливішу частину (як вони працюють), і що ви можете виконати те, що вам потрібно, кількома різними способами, моя відповідь на ваше запитання: це проблема розробника.


0

Я, звичайно, знаю програми, які широко роблять це, використовуючи кілька ідентифікаторів сеансу - і, схоже, працюють послідовно. Однак я не знаю - і не маю наміру з’ясовувати - чи вони це роблять, оскільки браузер повертає файли cookie у послідовному порядку, залежно від того, коли вони були встановлені / для якого шляху вони були встановлені, чи чи намагається програма відповідати кожному один до існуючого сеансу.

Я настійно рекомендую уникати цієї практики.

Однак якщо ви дійсно хочете знати, як браузери (та додатки) обробляють цей сценарій, чому б не створити тестову установку та не спробувати її.


2
Сервер не має контролю над тим, що йому надсилає браузер. З цим ще потрібно впоратися.
Мартін Оконнор,

0

Якщо ви використовуєте фреймворк Java / Scala Play: стережіться! Якщо запит містить кілька файлів cookie з однаковим іменем, Play подасть лише 1 із них до вашого коду.


-2

Якщо вам потрібно відрізнити їх, ви повинні дати їм різні ключові значення.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.