Файлы cookie на локальном хосте с явным доменом

191

Я, должно быть, упускаю некоторые основные вещи о куки. На localhost, когда я устанавливаю cookie на стороне сервера и указываю домен явно как localhost (или .localhost). cookie не принимается некоторыми браузерами.

Firefox 3.5: я проверил HTTP-запрос в Firebug. Что я вижу это:

Set-Cookie:
    name=value;
    domain=localhost;
    expires=Thu, 16-Jul-2009 21:25:05 GMT;
    path=/

или (когда я устанавливаю домен в .localhost):

Set-Cookie:
    name=value;
    domain=.localhost;
    expires=Thu, 16-Jul-2009 21:25:05 GMT;
    path=/

В любом случае, cookie не сохраняется.

IE8: я не использовал никаких дополнительных инструментов, но cookie, похоже, тоже не сохраняется, потому что он не отправляется обратно в последующих запросах.

Opera 9.64: и localhost, и .localhost работают , но когда я проверяю список файлов cookie в настройках, для домена устанавливается значение localhost.local, даже если он указан в списке localhost (в списке групп).

Safari 4: оба localhost и .localhost работают , но они всегда указаны в настройках как .localhost. С другой стороны, cookie без явного домена, он отображается как просто localhost (без точки).

В чем проблема с localhost? Из-за такого количества несоответствий должны быть специальные правила, касающиеся localhost. Кроме того, мне не совсем понятно, почему домены должны начинаться с префикса? RFC 2109 прямо заявляет, что:

Значение атрибута Domain не содержит встроенных точек или не начинается с точки.

Зачем? В документе указывается, что это связано с безопасностью. Я должен признать, что я не прочитал всю спецификацию (возможно, сделаю это позже), но это звучит немного странно. Исходя из этого, установка куки на localhost будет невозможна.

Ян Зич
источник
14
6 лет нить и это все еще проблема. Я использую Chrome v40. Смотрите здесь .
Гауи
5
Chrome 43 ... все еще ошибка.
Эван Кэрролл
4
Хром 54 здесь, НЕ решен
Вахид Амири
6
Chrome 73 .. все еще сталкивается с той же проблемой. :(
Code_Crash
2
Кто-нибудь может решить это? Все еще сталкиваюсь с той же самой
дерьмом

Ответы:

236

По своему дизайну доменные имена должны иметь как минимум две точки; в противном случае браузер сочтет их недействительными. (См. Ссылку на http://curl.haxx.se/rfc/cookie_spec.html. ).

При работе localhostдомен cookie должен быть полностью опущен. Просто установив его ""или NULLили FALSEвместо"localhost" этого недостаточно.

Для PHP см. Комментарии на http://php.net/manual/en/function.setcookie.php#73107 .

Если вы работаете с Java Servlet API, не вызывайте cookie.setDomain("...")метод вообще.

Ральф Бухфельдер
источник
93
Не уверен, почему все + 1 делают это, я установил для домена cookie значение null, false или пустую строку, и он все равно не сохраняется, если на локальном хосте.
Джастин
5
Я не вижу в RFC6265 двух точек в домене: tools.ietf.org/html/rfc6265#section-5.2.3 .Net говорит, что для всех хостов в вашем локальном домене установлено значение «.local». Что кажется совместимым с Opera / Safari msdn.microsoft.com/en-us/library/ckch3yd2.aspx
MandoMando
9
@Justin: Хм, вам, вероятно, нужно полностью пропустить Domain=параметр при установке cookie. Если вы просто установите домен в null или пустой, возможно, ваша структура отправит Domain=параметр с этим значением, а не пропустит его? Проверьте, например, Firebug.
слеске
2
@ Ральф, спасибо за миллион, эта штука сводила меня с ума на несколько часов. Надеюсь, установка для домена значения null (я нахожусь в стеке .Net server) работает как шарм.
Xose Lluis
4
Это несколько плохо сформулировано. «Установка на ноль, или ложь, или на пустую строку» должна гласить «Не устанавливать« cookie »часть файла cookie». Например, использование простого теста для полного исключения домена из раздела cookie работает для localhost:((domain && domain !== "localhost") ? ";domain="+domain : "")
L0j1k
34

Я в целом согласен с @Ralph Buchfelder, но здесь приведено некоторое усиление этого экспериментом при попытке реплицировать систему с несколькими поддоменами (например, example.com, fr.example.com, de.example.com) на моей локальной машине ( OS X / Apache / Chrome | Firefox).

Я отредактировал / etc / hosts, чтобы указать несколько воображаемых поддоменов на 127.0.0.1:

127.0.0.1 localexample.com
127.0.0.1 fr.localexample.com
127.0.0.1 de.localexample.com

Если я работаю на fr.localexample.com и не указываю параметр домена, файл cookie правильно сохраняется для fr.localexample.com, но не отображается в других поддоменах.

Если я использую домен ".localexample.com", файл cookie правильно сохраняется для fr.localexample.com, и это видно в других поддоменов.

Если я использую домен "localexample.com" или когда я пробовал домен только "localexample" или "localhost", cookie не сохранялся.

Если я использую домен "fr.localexample.com" или ".fr.localexample.com", файл cookie правильно сохраняется для fr.localexample.com и (правильно) невидим в других поддоменах.

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

Если кто-то хочет попробовать это, вот несколько полезных кодов:

<html>
<head>
<title>
Testing cookies
</title>
</head>
<body>
<?php
header('HTTP/1.0 200');
$domain = 'fr.localexample.com';    // Change this to the domain you want to test.
if (!empty($_GET['v'])) {
    $val = $_GET['v'];
    print "Setting cookie to $val<br/>";
    setcookie("mycookie", $val, time() + 48 * 3600, '/', $domain);
}
print "<pre>";
print "Cookie:<br/>";
var_dump($_COOKIE);
print "Server:<br/>";
var_dump($_SERVER);
print "</pre>";
?>
</body>
</html>
xgretsch
источник
30

localhost: вы можете использовать: domain: ".app.localhost"и это будет работать. Параметру 'domain' требуется 1 или более точек в имени домена для настройки файлов cookie. Тогда вы можете иметь сеансы работы через локальные поддомены , такие как: api.app.localhost:3000.

Ampt
источник
1
Также протестирован и работает на сервере node.js, используя Express 3.x, вexpress.session({cookie: { domain: '.app.localhost', maxAge: 24 * 60 * 60 * 1000 }})
AmpT
3
ЭТО должно быть выбрано в качестве ответа, если вы используете локальные домены! Помещение точки перед поддоменом решает мою проблему.
Foxhoundn
1
Так откуда же это ожидание .app.пришествия? Это часть какой-то SPEC? И применимо ли это для всех несоответствующих доменов (без двух точек)? Кроме того, это будет работать со старыми браузерами? : ^)
user2173353 15.12.16
Ох ... теперь я понимаю ... Это просто обман, чтобы обмануть браузеры. ХОРОШО.
user2173353
14

Когда cookie установлен с явным доменом 'localhost' следующим образом ...

Set-Cookie: имя = значение; домен = localhost ; истекает = чт, 16 июля 2009 21:25:05 мск; Путь = /

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

... домены должны иметь по крайней мере два (2) или три (3) периода в них для предотвращения доменов в форме: ".com", ".edu" и "va.us". Любой домен, который выходит из строя в одном из семи специальных доменов верхнего уровня, перечисленных ниже, требует только двух периодов. Любой другой домен требует как минимум три. Семь специальных доменов верхнего уровня: «COM», «EDU», «NET», «ORG», «GOV», «MIL» и «INT».

Обратите внимание, что число периодов выше, вероятно, предполагает, что требуется ведущий период. Этот период, однако, игнорируется в современных браузерах, и его, вероятно, следует читать ...

по крайней мере, один (1) или два (2) периода

Обратите внимание, что значением по умолчанию для атрибута домена является имя хоста сервера, который сгенерировал ответ cookie .

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

Скотт Мунро
источник
Я не сделал DV, но я предполагаю, что причина, по которой это сделали другие, заключается в том, что ваш ответ на самом деле не добавляет особой ценности. Требование двух периодов и оставление атрибута домена пустым были обсуждены в других ответах. Кроме того, материал, который вы добавили о домене верхнего уровня, кажется неправильным. По моему опыту, это не является обязательным требованием.
TTT
@TTT Не уверен, добрались ли вы до мелочей в моем ответе, где я говорю, что это должно быть по крайней мере 1 или два периода в зависимости от TLD, потому что ведущие периоды игнорируются? Поэтому я предоставил некоторую предысторию проблемы и добавил пункт, который, я думаю, не рассматривается в другом месте - правила отличаются для явного домена и того, к которому по умолчанию обращается браузер. Похоже, это добавляет некоторую ценность для меня.
Скотт Манро
1
Если оставить домен пустым (вообще не устанавливать его), то Chrome не сохранит cookie для localhost. Это все еще игнорирует это. Обратите внимание, что это относится только к «постоянным» cookie-файлам (те, которые устанавливают дату истечения срока действия), потому что они будут зависеть от «сеансовых» cookie-файлов для localhost (те, которые не устанавливают дату истечения срока действия)
Трийнко
3

Результаты, которые я изменил в браузере.

Chrome-127.0.0.1 работал, но localhost .localhost и "" не работали. Firefox- .localhost работал, но localhost, 127.0.0.1 и "" не работали.

Не тестировали в Opera, IE или Safari


источник
3
Только что проверил это с Chrome V.22.0.1229.94 m: Установка cookie для localhost без указания Domain=параметра работает. Domain=тоже работает, но Domain=localhostнет.
слеске
3

Потратил много времени на устранение этой проблемы самостоятельно.

Использование PHP, и ничего на этой странице не работает для меня. В конце концов я понял в своем коде, что параметр «secure» для PHP для session_set_cookie_params () всегда был установлен в TRUE.

Так как я не посещал localhost с https, мой браузер никогда не будет принимать cookie. Итак, я изменил эту часть своего кода, чтобы условно установить параметр «secure», основываясь на том, что $ _SERVER ['HTTP_HOST'] равен 'localhost' или нет. Работает хорошо сейчас.

Я надеюсь, что это поможет кому-то.

Джеймс Джейкобсон
источник
2

Если вы устанавливаете cookie из другого домена (то есть вы устанавливаете cookie, отправляя запрос XHR с перекрестным происхождением), то вам нужно убедиться, что для withCredentialsатрибута установлено значение true в XMLHttpRequest, который вы используете для получения cookie, как описано здесь

Эйдан Юэн
источник
да даже с этим. Это все еще не работает с междоменными запросами. Браузер - Safari, IE 11
Рохит Кумар
2

Вы можете использовать localhost.orgили, скорее, .localhost.orgон всегда будет разрешать127.0.0.1

qoomon
источник
1

Мне повезло, когда я тестировал локально, используя 127.0.0.1 в качестве домена. Я не уверен почему, но у меня были смешанные результаты с localhost и .localhost и т. Д.

Тоби
источник
1

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

В конце я просто удалил домен из cookie, если это localhost, и теперь он работает для меня в Chrome 38 .

Предыдущий код (не работал):

document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';

Новый код (сейчас работает):

 if(document.domain === 'localhost') {
        document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';path=/;' ;
    } else {
        document.cookie = encodeURI(key) + '=' + encodeURI(value) + ';domain=.' + document.domain + ';path=/;';
    }
DJ_Polly
источник
1

У меня была та же проблема, и я исправил ее, поместив 2 точки в самом имени файла cookie без указания какого-либо домена.

set-cookie: name.s1.s2=value; path=/; expires=Sun, 12 Aug 2018 14:28:43 GMT; HttpOnly
Эрик Б.
источник
1

Кажется, есть проблема, когда вы используете, https://<local-domain>а затем http://<local-domain>. http://Сайт не посылает печенье с запросами после https://множества сайтов им. Принудительная перезагрузка и очистка кеша не помогают. Работает только ручная очистка куки. Кроме того, если я очистить их на https://странице, тоhttp:// страница снова начинает работать.

Похоже, связано с "Строго безопасные куки". Хорошее объяснение здесь . Был выпущен в Chrome 58 2017-04-19.

Похоже, что на самом деле Chrome записывает как безопасные, так и небезопасные файлы cookie, поскольку при нажатии на значок в адресной строке будут отображаться правильные файлы cookie в зависимости от протокола страницы.

Но Developer tools > Application > Cookiesне будет отображать незащищенный файл cookie, когда существует безопасный файл cookie с тем же именем для того же домена, а также не будет отправлять незащищенный файл cookie с любыми запросами. Это похоже на ошибку Chrome, или, если ожидается такое поведение, должен быть какой-то способ просмотра безопасных файлов cookie приhttp странице и указания, что они переопределяются.

Обходной путь - использовать разные именованные куки-файлы в зависимости от того, предназначены ли они для http-сайта или https-сайта, и называть их в зависимости от вашего приложения. __Secure-Префикс указывает на то, что куки должны быть строго в безопасности, а также является хорошей практикой , так как безопасный и незащищенное не будут сталкиваться. Есть и другие преимущества префиксов .

Использование разных /etc/hostsдоменов для https и http-доступа тоже https://localhostподойдет , но одно случайное посещение предотвратит работу куки-файлов с одинаковыми именами на http://localhostсайтах - так что это не хороший обходной путь.

Я подал отчет об ошибке Chrome .

Vaughan
источник
0

document.cookie = valuename + "=" + value + ";" + expires + "; домен =; путь = /";

это "домен =; путь = /"; будет принимать динамический домен, так как его cookie будет работать в поддомене. если вы хотите проверить в localhost, он будет работать

Абхишек Синха
источник
0

Ни один из ответов здесь не работал для меня. Я исправил это, поместив свой PHP как самую первую вещь на странице.

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

От http://php.net/manual/en/function.setcookie.php

Джон Ктехик
источник
это не имеет ничего общего с проблемой, просто не делает ошибку, посылая любые другие выходные данные перед заголовками
Marnes
0

Я немного поиграл.

Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=localhost; Path=/

работает в Firefox и Chrome на сегодняшний день. Однако я не нашел способа заставить его работать с curl. Я попробовал Host-Header и --resolve, не повезло, любая помощь приветствуется.

Тем не менее, он работает в curl, если я установил его

Set-Cookie: _xsrf=2|f1313120|17df429d33515874d3e571d1c5ee2677|1485812120; Domain=127.0.0.1; Path=/

вместо. (Который не работает с Firefox.)

Миха
источник
0

Еще одна важная деталь : expires = должен использовать следующий формат даты и времени: Wdy, DD-Mon-YYYY HH: MM: SS GMT ( RFC6265 - Раздел 4.1.1 ).

Set-Cookie:
  name=value;
  domain=localhost;
  expires=Thu, 16-07-2019 21:25:05 GMT;
  path=/
Tralamazza
источник
5
-1 Текущей спецификацией для файлов cookie является RFC 6265, tools.ietf.org/html/rfc6265 , в которой прямо указано, что разрешены 4-значные годы. Поэтому плохая идея использовать двухзначные годы, которые разные браузеры будут интерпретировать по-разному.
слеске
Верный. Ссылка RFC6265, раздел 4.1.1
Корзина Zen
4
Правильно, но в июне 2011 года я не нашел этот RFC. Так что, хотя эта информация сейчас неверна, назад, когда я написал, ее не было.
Tralamazza
4
Не воспринимайте это как незначительное, все меняется, и мы все должны помочь обеспечить актуальность ответов. Просто обновите свой ответ последней информацией, которую @sleske дал вам, и поблагодарите его за помощь.
Мэтью Пурдон
0

После долгих экспериментов и чтения различных постов это сработало. Я мог бы установить несколько файлов cookie, прочитать их обратно, установить отрицательное время и удалить их.

func addCookie(w http.ResponseWriter, name string, value string) {
    expire := time.Now().AddDate(0, 0, 1)
    cookie := http.Cookie{
       Name:    name,
       Value:   value,
       Expires: expire,
       Domain:  ".localhost",
       Path:    "/",
    }
    http.SetCookie(w, &cookie)
}
Сайед
источник
0

Единственное, что сработало для меня, это установить Path=/печенье.

Более того, значение атрибута пути по умолчанию отличается от браузера к браузеру, хотя я протестировал только два из них (Firefox и Chrome).

Chrome пытается установить cookie как есть; если pathатрибут не указан в Set-Cookieзаголовке, он не будет сохранен и проигнорирован.

Тем не менее, Firefox хранит cookie даже без явного pathатрибута. Это просто установить его с запрошенным путем; URL моего запроса был /api/v1/usersи путь был установлен /api/v1автоматически.

Во всяком случае, оба браузера работали, когда pathбыло установлено /даже без явного домена, то есть Domain=localhostили что-то. Таким образом, существуют некоторые различия в том, как каждый браузер обрабатывает файлы cookie.

이준형
источник