Jakie znaki są dozwolone w plikach cookie?

Jakie są dozwolone znaki w nazwie i wartości pliku cookie? Czy są takie same jak URL lub jakiś wspólny podzbiór?

Pytam o to, że ostatnio natrafiłem na dziwne zachowanie z plikami cookie, które mają - w nazwie i zastanawiam się, czy to coś konkretnego dla przeglądarki, czy mój kod jest wadliwy.

 317
Author: YakovL, 2009-12-28

13 answers

Ten to szybki numerek:

Może i tak powinno być, ale tak naprawdę wcale nie jest!

Jakie są dozwolone znaki w nazwie i wartości pliku cookie?

Według starożytnego Netscape cookie_spec cały NAME=VALUE ciąg znaków to:

Sekwencja znaków z wyłączeniem dwukropków, przecinków i spacji.

Więc - powinno działać, a w przeglądarkach wydaje mi się, że jest OK; gdzie masz z tym problem?

Przez implikację powyższego:

  • = jest legalne, ale potencjalnie niejednoznaczne. Przeglądarki zawsze dzielą nazwę i wartość na pierwszy symbol = w łańcuchu, więc w praktyce można umieścić symbol = w wartości, ale nie nazwę.
Netscape nie jest znany, ponieważ Netscape był okropny w pisaniu specyfikacji, ale wydaje się być konsekwentnie wspierany przez przeglądarki:]}
  • Nazwę lub wartość może być pustymi łańcuchami

  • Jeśli w łańcuchu nie ma symbolu =, przeglądarki traktują go jako plik cookie o pustym łańcuchu, tzn. Set-Cookie: foo jest taki sam jak Set-Cookie: =foo.

  • Gdy przeglądarki wypisują plik cookie z pustą nazwą, pomijają znak równości. Więc Set-Cookie: =bar rodzi Cookie: bar.

  • Przecinki i spacje w nazwach i wartościach wydają się działać, chociaż spacje wokół znaku równości są przycięte

  • Kontrola znaki (\x00 do \x1F plus \x7F) nie są dozwolone

To, o czym nie wspomniano, a przeglądarki są całkowicie niespójne, to znaki nie-ASCII (Unicode):
    W Operze i Google Chrome są one kodowane do nagłówków plików Cookie za pomocą UTF-8.]} W IE używana jest domyślna strona kodowa maszyny (specyficzna dla locale i nigdy UTF-8);
  • Firefox (i inne przeglądarki oparte na Mozilli) używają niskiego bajtu każdego punktu kodu UTF-16 samodzielnie (więc ISO-8859-1 jest OK ale wszystko inne jest pokręcone);
  • Safari po prostu odmawia wysyłania plików cookie zawierających znaki inne niż ASCII.

W praktyce nie można w ogóle używać znaków innych niż ASCII w plikach cookie. Jeśli chcesz użyć Unicode, kodów sterujących lub innych dowolnych sekwencji bajtów, cookie_spec wymaga użycia własnego schematu kodowania ad-hoc i sugerowania kodowania URL (produkowanego przez JavaScript encodeURIComponent) jako rozsądnego wyboru.

W kategoriach rzeczywistych standardy, było kilka prób kodyfikacji zachowania plików cookie, ale do tej pory żadna nie odzwierciedla rzeczywistego świata.

  • RFC 2109 było próbą kodyfikacji i naprawy oryginalnego Netscape cookie_spec. W tym standardzie wiele innych znaków specjalnych jest niedozwolonych, ponieważ używa tokenów RFC 2616 (a -to nadal ), a tylko wartość może być podana w cudzysłowu z innymi znakami. Żadna przeglądarka nigdy nie zaimplementowała ograniczenia, Specjalna obsługa cytowanych łańcuchów i znaków specjalnych lub nowe funkcje w tej specyfikacji.

  • RFC 2965 było kolejnym krokiem w tym kierunku, porządkując 2109 i dodając więcej funkcji w ramach schematu "Wersja 2 cookies". Tego też nikt nigdy nie zrealizował. Ta specyfikacja ma takie same ograniczenia token-and-quoted-string jak wcześniejsza wersja i jest to tak samo stek bzdur.

  • RFC 6265 jest próbą oczyszczenia historyczny bałagan. Nadal nie pasuje do rzeczywistości, ale jest o wiele lepiej niż wcześniejsze próby-jest to przynajmniej odpowiedni podzbiór tego, co obsługują przeglądarki, nie wprowadzając żadnej składni, która ma działać, ale nie (jak poprzedni cytowany-string).

W 6265 nazwa pliku cookie jest nadal określona jako RFC 2616 token, co oznacza, że możesz wybrać z alphanums plus:
!#$%&'*+-.^_`|~

W wartości pliku cookie formalnie blokuje kontrolę (filtrowaną przez przeglądarki znaki i (niespójnie zaimplementowane) znaki nie-ASCII. Zachowuje zakaz cookie_spec dotyczący spacji, przecinków i średników, plus dla kompatybilności z biednymi idiotami, którzy faktycznie zaimplementowali wcześniejsze RFC, zakazuje również odwrotnego ukośnika i cudzysłowów, innych niż cudzysłowy owijające całą wartość (ale w takim przypadku cytaty są nadal uważane za część wartości, a nie schemat kodowania). Więc zostajesz z alphanums plus:

!#$%&'()*+-./:<=>?@[]^_`{|}~

W realnym świecie wciąż używamy oryginalny - i-najgorszy Netscape cookie_spec, więc kod, który zużywa pliki cookie powinien być przygotowany na napotkanie prawie wszystkiego, ale dla kodu, który produkuje pliki cookie, zaleca się trzymać się podzbioru w RFC 6265.

 402
Author: bobince,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-28 09:06:49

W ASP.Net możesz użyć System.Web.HttpUtility, Aby bezpiecznie zakodować wartość pliku cookie przed zapisaniem do pliku cookie i przekonwertować ją z powrotem do pierwotnej formy po odczytaniu.

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

Spowoduje to zatrzymanie znaków Ampersand i equals dzielących wartość na kilka par nazwa / wartość, które są zapisywane w pliku cookie.

 28
Author: stephen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-28 15:34:58

Myślę, że jest to ogólnie specyficzne dla przeglądarki. Aby zachować bezpieczeństwo, base64 koduje obiekt JSON i przechowuje w nim wszystko. W ten sposób musisz go tylko odszyfrować i przeanalizować JSON. Wszystkie znaki używane w base64 powinny grać dobrze z większości, jeśli nie wszystkich przeglądarek.

 18
Author: Jamie Rumbelow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-12-28 12:25:01

Oto, w jak najmniejszej liczbie słów . Skup się na postaciach, które nie potrzebują ucieczki:

Dla plików cookie:

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'()*+-./:<>?@[]^_`{|}~

Dla adresów URL

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789.-_~!$&'()*+,;=:@

Dla plików cookie i adresów URL (7)]}

abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!$&'()*+-.:@_~
Tak odpowiadasz.

Należy pamiętać, że w przypadku plików cookie,= został usunięty, ponieważ jest zwykle używane do ustawiania wartości pliku cookie.

Dla adresów URL ten = został zachowany. Skrzyżowanie jest oczywiście bez.

var chars = "abdefghijklmnqrstuvxyz"; chars += chars.toUpperCase() + "0123456789" + "!$&'()*+-.:@_~";

Okazuje się, że wciąż dochodzi do ucieczki i nieoczekiwanego zdarzenia, szczególnie w środowisku Java cookie, gdzie plik cookie jest owinięty podwójnymi cudzysłowami, jeśli napotka ostatnie znaki.

Więc dla bezpieczeństwa, użyj A-Za-z1-9. To właśnie zamierzam zrobić.
 15
Author: mmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 14:01:57

Nowszy rfc6265 opublikowany w kwietniu 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

Jeśli spojrzysz na @bobince odpowiedź widzisz, że nowsze ograniczenia są bardziej rygorystyczne.

 12
Author: gavenkoa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-04 18:51:01

Nie można umieścić ";" w polu Wartość pliku cookie, nazwa, która zostanie ustawiona jest ciągiem znaków aż do";"w większości przeglądarek...

 7
Author: hagay onn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-05 15:17:51

Istnieją 2 wersje specyfikacji plików cookie
1. Wersja 0 cookies aka Netscape cookies,
2. Wersja 1 aka RFC 2965 cookies
W wersji 0 częścią nazwy i wartości plików cookie są sekwencje znaków, z wyłączeniem średnika, przecinka, znaku równości i spacji, jeśli nie są używane z podwójnymi cudzysłowami
Wersja 1 jest o wiele bardziej skomplikowana możesz ją sprawdzić tutaj
W tej wersji specyfikacja dla nazwy wartość części jest prawie taka sama, z tym, że nazwa nie może zaczynać się od $ sign

 2
Author: Tinku,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-06 15:54:56

Jest jeszcze jeden interesujący problem z IE i Edge. Pliki cookie o nazwach dłuższych niż 1 Okres wydają się być po cichu usuwane. Więc To działa:

Cookie_name_a=valuea

While this will get dropped

Cookie. name. a=valuea

 1
Author: Arvoreen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-18 05:18:16

To proste:

A może być dowolnymi znakami US-ASCII z wyjątkiem control znaki (CTL), spacje lub tabulatory. Nie może również zawierać znak separatora jak poniżej: ( ) @ , ; : \ " / [ ] ? = { }.

Wartość może być opcjonalnie ustawiona w podwójnych cudzysłowach i dowolnych Znaki US-ASCII z wyłączeniem CTL, whitespace, double quotes, comma, średnik i Ukośnik są dozwolone. Kodowanie: wiele implementacji wykonaj kodowanie URL na wartościach plików cookie, jednak nie jest wymagane na Specyfikacja RFC. Pomaga spełnić wymagania dotyczące które znaki są jednak dozwolone.

Link: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives

 1
Author: webolizzer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Jeszcze jedna uwaga. Niedawno zaimplementowałem schemat, w którym niektóre poufne dane wysłane do skryptu PHP musiały zostać przekonwertowane i zwrócone jako zaszyfrowane pliki cookie, które wykorzystywały wszystkie wartości base64, które uważałem za gwarantowane "bezpieczne". Więc posłusznie zaszyfrowałem elementy danych za pomocą RC4, przepuściłem wyjście przez base64_encode i szczęśliwie zwróciłem plik cookie na stronę. Testowanie wydawało się przebiegać dobrze, dopóki zakodowany ciąg znaków base64 nie zawierał symbolu"+". Ciąg został zapisany na stronie bez kłopoty. Korzystając z diagnostyki przeglądarki mogłem również zweryfikować, czy pliki cookie zostały zapisane w niezmienionej formie. Następnie, gdy Następna strona wywołała moje PHP i uzyskała plik cookie za pośrednictwem tablicy $_COOKIE, jąkałem się, aby znaleźć ciąg znaków brakowało teraz znaku"+". Każde wystąpienie tego znaku zostało zastąpione spacją ASCII.

Biorąc pod uwagę, ile podobnych nierozwiązanych skarg przeczytałem opisując ten scenariusz od tego czasu, często umieszczając liczne odniesienia do używania base64 do "bezpiecznego" sklepu dowolne dane w plikach cookie, pomyślałem, że wskażę problem i zaproponuję moje rozwiązanie.

Po wykonaniu dowolnego szyfrowania na kawałku danych, a następnie użyciu base64_encode, aby uczynić go "bezpiecznym dla plików cookie", Uruchom ciąg wyjściowy przez to...

// 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;
    }

Tutaj po prostu zastępuję " + "(i zdecydowałem"=") innymi" cookie safe " znakami, przed zwróceniem zakodowanej wartości na stronę, do wykorzystania jako plik cookie. Należy pamiętać, że długość przetwarzany ciąg znaków nie zmienia się. Gdy ta sama (lub inna strona na stronie) uruchomi mój skrypt PHP ponownie, będę mógł odzyskać ten plik cookie bez brakujących znaków. Muszę tylko pamiętać, aby przekazać ciasteczko z powrotem przez to samo wywołanie fix64 (), które utworzyłem, i stamtąd mogę je odszyfrować za pomocą zwykłej metody base64_decode (), a następnie dowolnych innych deszyfrowań w twoim schemacie.

Może być jakieś ustawienie, które mógłbym zrobić w PHP, które pozwala na przesyłanie ciągów base64 używanych w plikach cookie powrót do PHP bez korupcji. W międzyczasie to działa. "+"Może być" legalną " wartością pliku cookie, ale jeśli chcesz być w stanie przesłać taki ciąg z powrotem do PHP( w moim przypadku przez tablicę $_cookie), sugeruję ponowne przetworzenie w celu usunięcia obrażających znaków i przywrócenia ich po odzyskaniu. Istnieje wiele innych" cookie safe " znaków do wyboru.

 0
Author: Randy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-07-03 14:42:18

Jeśli używasz zmiennych później, przekonasz się, że rzeczy takie jak path faktycznie przepuszczają znaki z akcentami, ale nie pasują do ścieżki przeglądarki. W tym celu musisz je URIEncode. Czyli tak:

  const encodedPath = encodeURI(myPath);
  document.cookie = `use_pwa=true; domain=${location.host}; path=${encodedPath};`

Więc "dozwolone" znaki, może być więcej niż to, co jest w specyfikacji. Ale powinieneś trzymać się specyfikacji i używać ciągów zakodowanych URI, aby być bezpiecznym.

 0
Author: odinho - Velmont,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-12-04 14:24:48

Lata temu MSIE 5 lub 5.5 (i prawdopodobnie oba) miał jakiś poważny problem z " - " w bloku HTML, jeśli można w to uwierzyć. Alhough nie jest to bezpośrednio powiązane, odkąd przechowujemy hash MD5 (zawierający tylko litery i cyfry) w pliku cookie, aby wyszukać Wszystko inne w bazie danych po stronie serwera.

 -1
Author: FYA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-25 18:59:50

Skończyło się na użyciu

cookie_value = encodeURIComponent(my_string);

I

my_string = decodeURIComponent(cookie_value);

To wydaje się działać dla wszystkich rodzajów znaków. W przeciwnym razie miałem dziwne problemy, nawet z znakami, które nie były średnikami ani przecinkami.

 -1
Author: user984003,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-07 15:32:33