Как обрабатывать несколько файлов 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? Или такой случай следует рассматривать как ошибку разработчика?

Deamon
источник
Я бы сделал все возможное (читайте: все, что могу), чтобы избежать дублирования имен файлов cookie. Большинство людей никогда не сталкивались с этой проблемой по уважительной причине.
Веб-сайт может читать только свои собственные файлы cookie. Он не может читать cookie другого веб-сайта / домена. Эта безопасность обеспечивается браузером. Это может быть совет для абсолютных новичков (у меня была эта путаница)
Арун

Ответы:

38

Из этой статьи на SitePoint :

Если несколько файлов cookie с одним и тем же именем соответствуют заданному URI запроса, браузер выбирает один.

Чем конкретнее путь, тем выше приоритет. Однако приоритет, основанный на других атрибутах, включая домен, не указан и может различаться в зависимости от браузера. Это означает, что если вы установили файлы cookie с тем же именем для «.example.org» и «www.example.org», вы не можете быть уверены, какое из них будет отправлено обратно.

Изменить: эта информация с 2010 года кажется устаревшей, похоже, браузеры теперь могут отправлять несколько файлов cookie взамен, подробности см. В ответе @Nate ниже.

Ян М
источник
9
Итак, как можно удалить несколько одинаковых файлов cookie? Я забиваю это уже два дня, и дублирующиеся куки кажутся неразрушимыми.
Боб Джонс,
13
@Brant Эта статья может быть немного некорректной - я только что видел, как Chrome отправляет два файла cookie с одинаковым именем (но разными путями) обратно, поэтому «один выбирается браузером» не обязательно верно. Первым был отправлен файл cookie с самым глубоким путем, BTW, что кажется разумным. И еще одно печенье тоже было между ними.
Jonas N
3
Firefox (15) также отправляет два файла cookie с одинаковым именем! если он столкнулся с двумя куки-файлами с для домена .a.comи хостаa.com
Таха Джахангир
Действительно, эта информация неверна. Ответ @Nate должен быть отмечен как правильный.
Дэн Милон
5
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 с одинаковым именем (например, которые были установлены с разными атрибутами Path или Domain), серверам НЕ СЛЕДУЕТ полагаться на порядок, в котором эти файлы 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 = /; Путь = /; Версия = 1
    • Set-cookie: a = 2 & path = / example; Path = / example; Version = 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.
Александр Шранц
1
Соответствует ли path=/;Path=/спецификация FRC-6265? Я не нашел такого упоминания. Угроза Tomcat любая ";" в пути как неправильный символ
Hubbitus
1
@Hubbitus Обратите внимание, это a=2&path=/example;Path=/exampleтак, что нет ;пути.
Франклин Ю
2

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

Если вы этого не сделаете, то, конечно, можно будет использовать разные имена, если вам нужны оба контекста.

Альтернативой является отправка того же имени файла cookie с тем же путем (и доменом) даже с более конкретных путей. Эти инструкции по установке файлов cookie перезапишут значение этого файла cookie.

Теперь, когда вы знаете самую важную часть (как они работают) и что вы можете выполнить то, что вам нужно, несколькими способами, мой ответ на ваш вопрос: это проблема разработчика.

Джерард Онил
источник
0

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

Я настоятельно рекомендую избегать этой практики.

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

symcbean
источник
2
Сервер не может контролировать то, что ему отправляет браузер. С этим еще нужно разобраться.
Мартин ОКоннор,
0

Если вы используете платформу Java / Scala Play: будьте осторожны! Если запрос содержит несколько файлов cookie с одним и тем же именем, Play предоставит вашему коду только 1 из них.

Эрик ван Остен
источник
-2

Если вам нужно различать их, вы должны дать им разные ключевые значения.

Йогурт
источник