Разрешенные символы в файлах cookie
этот быстрый:
Каковы допустимые символы в имени и значении cookie? Являются ли они такими же, как URL или некоторые общие подмножества?
Причина, о которой я прошу, заключается в том, что я недавно столкнулся с каким-то странным поведением с файлами cookie, которые имеют -
в своем имени, и мне просто интересно, не является ли это чем-то конкретным браузером или если мой код неисправен.
Ответы
Ответ 1
этот быстрый:
Вы можете подумать, что это должно быть, но на самом деле это совсем не так!
Каковы допустимые символы в имени и значении cookie?
В соответствии с древним Netscape cookie_spec вся строка NAME=VALUE
:
последовательность символов, исключая запятую, запятую и пробел.
Итак, -
должен работать, и в браузерах, которые у меня есть, все в порядке. где у вас проблемы с этим?
Подразумевается выше:
-
=
является законным включать, но потенциально двусмысленным. Браузеры всегда разделяют имя и значение на первом символе =
в строке, поэтому на практике вы можете поместить символ =
в VALUE, но не в ИМЯ.
Что не упоминается, потому что Netscape были ужасны при написании спецификаций, но, кажется, последовательно поддерживаются браузерами:
-
либо NAME, либо VALUE могут быть пустыми строками
-
если в строке вообще нет символа =
, браузеры рассматривают его как файл cookie с именем пустой строки, то есть Set-Cookie: foo
совпадает с Set-Cookie: =foo
.
-
когда браузеры выводят файл cookie с пустым именем, они опускают знак равенства. Итак, Set-Cookie: =bar
порождает Cookie: bar
.
-
запятые и пробелы в именах и значениях действительно работают, хотя пробелы вокруг знака равенства обрезаются
-
управляющие символы (\x00
- \x1F
plus \x7F
) не разрешены
Что не упоминается, и браузеры абсолютно несовместимы, это символы, отличные от ASCII (Unicode):
- в Opera и Google Chrome они закодированы в заголовки Cookie с UTF-8;
- в IE используется кодовая страница машины по умолчанию (специфичная для локали и никогда не UTF-8);
- Firefox (и другие браузеры на основе Mozilla) используют младший байт каждой кодовой точки UTF-16 самостоятельно (так что ISO-8859-1 в порядке, но все остальное искажено);
- Safari просто отказывается отправлять какие-либо файлы cookie, содержащие не-ASCII-символы.
поэтому на практике вы не можете использовать символы, отличные от ASCII, в файлах cookie. Если вы хотите использовать Unicode, управляющие коды или другие произвольные последовательности байтов, cookie_spec требует, чтобы вы использовали специальную схему кодирования по своему выбору и предлагали кодирование URL (как это было создано JavaScript encodeURIComponent
) в качестве разумного выбора.
С точки зрения фактических стандартов, было несколько попыток кодифицировать поведение cookie, но пока они фактически не отражают реальный мир.
-
RFC 2109 была попытка кодифицировать и исправить исходный файл cookie Netscape. В этом стандарте многие другие специальные символы запрещены, поскольку он использует RFC 2616 (a -
по-прежнему разрешено там), и только значение может указываться в кавычках с другими символами. Ни один браузер никогда не реализовал ограничения, специальную обработку цитированных строк и экранирование, а также новые функции в этой спецификации.
-
RFC 2965 - это еще один шаг к этому, уборка 2109 и добавление дополнительных функций в "куки-версию версии 2". Никто никогда не реализовал ни одно из них. Эта спецификация имеет те же ограничения на токен-и-кавычки, что и в более ранней версии, и на столько же нагрузка ерунды.
-
RFC 6265 - это попытка HTML5-эры для устранения исторического беспорядка. Он по-прежнему не соответствует действительности, но намного лучше, чем предыдущие попытки - это, по крайней мере, правильное подмножество того, что поддерживает браузер, а не введение какого-либо синтаксиса, который должен работать, но не (как и предыдущая кавычка).
В 6265 имя файла cookie все еще указано как RFC 2616 token
, что означает, что вы можете выбрать из букв плюс:
!#$%&'*+-.^_`|~
В значении cookie оно формально запрещает управляемые символы (отфильтрованные браузерами) и (непоследовательно-реализованные) символы, отличные от ASCII. Он сохраняет запрет cookie_spec на пространство, запятую и точку с запятой, а также для совместимости с любыми бедными идиотами, которые на самом деле реализовали предыдущие RFC, а также запретили обратную косую черту и кавычки, за исключением кавычек, обертывающих всю ценность (но в этом случае кавычки по-прежнему считаются частью значение, а не схема кодирования). Таким образом, вы получите букву плюс:
!#$%&'()*+-./:<=>[email protected][]^_`{|}~
В реальном мире мы по-прежнему используем оригинальный и худший Netscape cookie_spec, поэтому код, который потребляет файлы cookie, должен быть готов к тому, чтобы встречаться практически во всем, но для кода, который создает файлы cookie, желательно придерживаться подмножества в RFC 6265.
Ответ 2
В ASP.Net вы можете использовать System.Web.HttpUtility
, чтобы безопасно кодировать значение cookie перед записью в файл cookie и преобразовать его обратно в исходную форму при чтении.
// Encode
HttpUtility.UrlEncode(cookieData);
// Decode
HttpUtility.UrlDecode(encodedCookieData);
Это остановит амперсанды и примет знаки, разделяющие значение, на кучу пар имя/значение, поскольку оно записано в файл cookie.
Ответ 3
Я думаю, что это вообще браузер специфический. Чтобы быть в безопасности, base64 кодирует объект JSON и сохраняет все в этом. Таким образом, вам просто нужно его расшифровать и проанализировать JSON. Все символы, используемые в base64, должны отлично работать с большинством, если не во всех браузерах.
Ответ 4
Вот он, как можно меньше слов. Сосредоточьтесь на символах, которые не требуют экранирования:
Для файлов cookie:
abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'()*+-./:<>[email protected][]^_`{|}~
Для URL-адресов
abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789.-_~!$&'()*+,;=:@
Для файлов cookie и URL-адресов (пересечение)
abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!$&'()*+-.:@_~
Как вы отвечаете.
Обратите внимание, что для файлов cookie значение = было удалено, так как оно обычно используется для установки значения cookie.
Для URL-адресов это значение было сохранено. Пересечения, очевидно, нет.
var chars = "abdefghijklmnqrstuvxyz"; chars += chars.toUpperCase() + "0123456789" + "!$&'()*+-.:@_~";
Выключает экранирование, которое все еще происходит и неожиданно происходит, особенно в среде Java cookie, где куки файл обернут двойными кавычками, если он встречает последние символы.
Чтобы быть в безопасности, просто используйте A-Za-z1-9. Это то, что я собираюсь делать.
Ответ 5
Более новый rfc6265, опубликованный в апреле 2011 года:
cookie-header = "Cookie:" OWS cookie-string OWS
cookie-string = cookie-pair *( ";" SP cookie-pair )
cookie-pair = cookie-name "=" cookie-value
cookie-value = *cookie-octet / ( DQUOTE *cookie-octet DQUOTE )
cookie-octet = %x21 / %x23-2B / %x2D-3A / %x3C-5B / %x5D-7E
; US-ASCII characters excluding CTLs,
; whitespace DQUOTE, comma, semicolon,
; and backslash
Если вы посмотрите на @bobince ответ, вы увидите, что более новое ограничение более строгое.
Ответ 6
вы не можете поставить ";" в поле значений файла cookie имя, которое будет установлено, является строкой до ";" в большинстве браузеров...
Ответ 7
Существует 2 версии спецификаций файлов cookie
1. Версия 0 cookie aka Файлы cookie Netscape,
2. Версия 1, а также cookie RFC 2965
В версии 0 Имя и значение части файлов cookie - это последовательности символов, исключая точку с запятой, запятую, знак равенства и пробелы, если они не используются с двойными кавычками
версия 1 намного сложнее, вы можете ее проверить здесь
В этой версии спецификация для части значения имени почти такая же, за исключением того, что имя не может начинаться со знака $sign
Ответ 8
Есть еще одна интересная проблема с IE и Edge. Файлы cookie с именами более 1 периода, по-видимому, молча отбрасываются. Так что это работает:
cookie_name_a = значение а
пока это упадет
cookie.name.a = значение а
Ответ 9
так просто:
<Cookie-name> может быть любым символом US-ASCII, кроме управляющих символов (CTL), пробелов или символов табуляции. Он также не должен содержать символ-разделитель, например:() <> @,; знак равно
<Cookie-значение> может быть необязательно установлено в двойных кавычках, и любые символы US-ASCII, за исключением CTL, пробелов, двойных кавычек, запятой, точки с запятой и обратной косой черты, допускаются. Кодировка. Многие реализации выполняют кодирование URL-адресов для значений файлов cookie, однако это не требуется согласно спецификации RFC. Это помогает удовлетворить требования о том, какие символы разрешены.
Ссылка: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives
Ответ 10
Еще одно соображение. Недавно я реализовал схему, в которой некоторые конфиденциальные данные, публикуемые в сценарии PHP, должны были преобразовываться и возвращаться в виде зашифрованного файла cookie, в котором использовались все значения base64, которые я считал гарантированно "безопасными". Поэтому я должным образом зашифровал элементы данных с помощью RC4, запустив вывод через base64_encode и благополучно вернул cookie на сайт. Тестирование шло хорошо, пока строка в кодировке base64 не содержала символ "+". Строка была записана в cookie страницы без проблем. С помощью диагностики браузера я также мог убедитесь, что файлы cookie были записаны без изменений. Затем, когда на следующей странице был вызван мой PHP и получен файл cookie через массив $ _COOKIE, я заикался, обнаружив, что в строке теперь отсутствует знак "+". Каждое вхождение этого символа заменялось на Пространство ASCII.
Учитывая, сколько подобных неразрешенных жалоб я прочитал, описывая этот сценарий с тех пор, часто размещая многочисленные ссылки на использование base64 для "безопасного" хранения произвольных данных в файлах cookie, я подумал, что укажу на проблему и предложу свое заведомо грязное решение.
После того, как вы выполнили любое шифрование для части данных, а затем использовали base64_encode, чтобы сделать его "cookie-безопасным", пропустите строку вывода через это...
// from browser to PHP. substitute troublesome chars with
// other cookie safe chars, or vis-versa.
function fix64($inp) {
$out =$inp;
for($i = 0; $i < strlen($inp); $i++) {
$c = $inp[$i];
switch ($c) {
case '+': $c = '*'; break; // definitly won't transfer!
case '*': $c = '+'; break;
case '=': $c = ':'; break; // = symbol seems like a bad idea
case ':': $c = '='; break;
default: continue;
}
$out[$i] = $c;
}
return $out;
}
Здесь я просто заменяю "+" (и я решил "=") другими символами "cookie", прежде чем возвращать закодированное значение на страницу для использования в качестве cookie. Обратите внимание, что длина обрабатываемой строки не изменяется. Когда тот же (или другая страница на сайте) снова запустит мой PHP-скрипт, я смогу восстановить этот cookie без пропущенных символов. Мне просто нужно помнить, чтобы передать cookie обратно через тот же вызов fix64(), который я создал, и оттуда я могу декодировать его с помощью обычной base64_decode(), за которой следует любая другая расшифровка в вашей схеме.
Могут быть некоторые настройки, которые я могу сделать в PHP, которые позволяют передавать строки base64, используемые в cookie, обратно в PHP без повреждения. В то же время это работает. "+" Может быть "допустимым" значением cookie, но если у вас есть желание передать такую строку обратно в PHP (в моем случае через массив $ _COOKIE), я предлагаю повторную обработку для удаления оскорблять персонажей и восстанавливать их после восстановления. Есть множество других "безопасных от печенья" символов на выбор.
Ответ 11
Несколько лет назад MSIE 5 или 5.5 (и, вероятно, оба) имели серьезную проблему с "-" в блоке HTML, если вы можете в это поверить. Хотя это не связано напрямую, с тех пор как мы сохранили хэш MD5 (содержащий только буквы и цифры) в файле cookie, чтобы найти все остальное в базе данных на стороне сервера.
Ответ 12
Я закончил тем, что использовал
cookie_value = encodeURIComponent(my_string);
и
my_string = decodeURIComponent(cookie_value);
Это похоже на все виды персонажей. В противном случае у меня были странные проблемы, даже с символами, которые не были точками с запятой или запятыми.