Çerezlerde izin verilen karakterler nelerdir?


301

Hem çerez adı hem de değerde izin verilen karakterler nelerdir? URL veya ortak bir alt kümeyle aynı mı?

Sormamın nedeni, son zamanlarda -kendi adlarına sahip çerezlerle bazı garip davranışlara çarptığım ve sadece tarayıcıya özgü bir şey mi yoksa kodumun hatalı olup olmadığını merak ediyorum.

Yanıtlar:


391

bu bir şipşak:

Olması gerektiğini düşünebilirsiniz, ama gerçekten hiç değil!

Hem çerez adı hem de değerde izin verilen karakterler nelerdir?

Eski Netscape cookie_spec'e göre tüm NAME=VALUEdize:

noktalı virgül, virgül ve beyaz boşluk hariç bir dizi karakter.

Bu yüzden -çalışmalı ve burada aldığım tarayıcılarda sorun yok gibi görünüyor; onunla nerde sorun yaşıyorsun?

Yukarıdakilerin uygulanmasıyla:

  • =dahil etmek yasaldır ancak potansiyel olarak belirsizdir. Tarayıcılar her zaman dizgideki ilk =sembolün adını ve değerini böler , böylece pratikte =NAME yerine DEĞER'e bir sembol koyabilirsiniz .

Bahsetmeyenler, çünkü Netscape teknik özellikleri yazmakta korkunçtu, ancak tarayıcılar tarafından sürekli olarak destekleniyor gibi görünüyor:

  • NAME veya VALUE boş dizeler olabilir

  • Hiçbir varsa =hiç dizesinde sembol, tarayıcılar boş-string adı ile çerez olarak davranın, yani Set-Cookie: fooaynıdır Set-Cookie: =foo.

  • tarayıcılar boş ada sahip bir çerez çıkardığında, eşittir işaretini atlarlar. Yani Set-Cookie: =barbaşlıyor Cookie: bar.

  • eşittir işaretinin etrafındaki boşluklar kesilmiş olsa da, ad ve değerlerde virgül ve boşluklar gerçekten işe yarıyor gibi görünüyor

  • (kontrol karakterleri \x00için \x1Fartı \x7F) izin verilmez

Bahsedilmeyen ve tarayıcılar tamamen tutarsız, ASCII olmayan (Unicode) karakterler:

  • Opera ve Google Chrome'da, UTF-8 ile Çerez başlıklarına kodlanırlar;
  • IE'de, makinenin varsayılan kod sayfası kullanılır (yerel ayara özgü ve asla UTF-8);
  • Firefox (ve diğer Mozilla tabanlı tarayıcılar) her UTF-16 kod noktasının düşük baytını tek başına kullanır (bu nedenle ISO-8859-1 uygundur, ancak başka bir şey karıştırılır);
  • Safari, ASCII olmayan karakterler içeren herhangi bir çerez göndermeyi reddediyor.

dolayısıyla pratikte çerezlerde ASCII olmayan karakterler kullanamazsınız. Unicode, kontrol kodları veya diğer rastgele bayt dizilerini kullanmak istiyorsanız, cookie_spec, kendi seçtiğiniz ad-hoc kodlama şemasını kullanmanızı ve encodeURIComponentmakul bir seçim olarak URL kodlamasını (JavaScript tarafından üretildiği gibi) önermenizi ister .

Gerçek standartlar açısından, çerez davranışını kodlamak için birkaç girişim olmuştur, ancak şimdiye kadar hiçbiri gerçek dünyayı yansıtmamaktadır.

  • RFC 2109 , orijinal Netscape cookie_spec kodunu düzeltme ve düzeltme girişimidir. Kullandığı olarak bu standart daha birçok özel karakterler olarak, izin verilmeyen RFC 2616 belirteçleri (a -edilir hala orada izin verilir) ve sadece değer diğer karakterler ile bir alıntı-string belirtilebilir. Hiçbir tarayıcı sınırlamaları, alıntılanan dizelerin ve kaçmanın özel işlenmesini veya bu spesifikasyondaki yeni özellikleri uygulamadı.

  • RFC 2965 , 2109'u toplayarak ve 'sürüm 2 çerezleri' şeması altında daha fazla özellik ekleyerek başka bir şeydi. Hiç kimse de bunlardan hiçbirini uygulamadı. Bu özellik, önceki sürümle aynı jeton ve alıntılanan dize sınırlamalarına sahiptir ve bu da bir saçmalık yüküdür.

  • RFC 6265 , tarihi karmaşayı temizlemek için HTML5 dönemli bir girişimdir. Hala gerçekle tam olarak eşleşmiyor, ancak önceki girişimlerden çok daha iyi - tarayıcıların desteklediği en azından uygun bir alt kümedir, çalışması gereken ancak söz konusu olmayan (önceki alıntılanan dize gibi) herhangi bir sözdizimi getirmiyor .

6265'te çerez adı hala bir RFC 2616 olarak belirtilir token, bu da alfanum plus'tan seçim yapabileceğiniz anlamına gelir:

!#$%&'*+-.^_`|~

Çerez değerinde (tarayıcılar tarafından filtrelenmiş) kontrol karakterlerini ve (tutarsız olarak uygulanan) ASCII olmayan karakterleri resmi olarak yasaklar. Cookie_spec'in boşluk, virgül ve noktalı virgül üzerindeki yasağını korur, ayrıca önceki RFC'leri gerçekten uygulayan kötü aptallarla uyumluluk için, tüm değeri saran tırnaklar dışında ters eğik çizgi ve tırnak işareti de yasakladı (ancak bu durumda tırnak işaretleri hala bir parçası olarak kabul edilir) değer, bir kodlama şeması değil). Böylece sizi alfanum plus ile birlikte bırakırsınız:

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

Gerçek dünyada hala orijinal ve en kötü Netscape cookie_spec'i kullanıyoruz, bu yüzden çerezleri tüketen kod hemen hemen her şeyle karşılaşmaya hazırlanmalı, ancak çerez üreten kod için RFC 6265'teki alt kümeye bağlı kalmanız önerilir.


@bobince RFC, çerez değerlerinin ;çift ​​tırnak işareti içine alındığı sürece karaktere sahip olabileceğini mi ifade ediyor ? Bu şekilde:Set-Cookie: Name=Va";"lue; Max-Age=3600
Pacerier

@Pacerier: Tüm değerin alıntılanmış bir dize olması gerekir, bu yüzden olması gerekir Name="Va;lue"; max-age.... Tarayıcılarda çalışmaz ve 2965'in yerini alması önerilen ve gerçekliği biraz daha iyi yansıtmaya çalışan RFC 6265'te izin verilmez.
bobince

@bobince - Bunun eski olduğunu biliyorum, ancak çerez değerlerinde boşluklara teknik olarak izin verilmediği anlamına gelen cevabınızı doğru okuyor muyum? "
noktalı

1
@Adam: Evet, Netscape spec veya RFC 6265'e gidiyorsanız, ham (DQUOTEd) çerez değerinde boşluklara izin verilmez. Yine de denediğim tarayıcılarda işe yarıyor, ama buna güvenmem.
bobince

2
RFC 6265 tanımlar olarak belirteci 1*<any CHAR except CTLs or separators>ve ayırıcılar (, ), <, >, @, ,, ;, :, \, ", /, [, ], ?, =, {, }, SPve HT, çerez adları alphanums olmalıdır böylece artı!#$%&'*+-.?^_`|~
Gan Quan

28

ASP.Net size kullanabilirsiniz System.Web.HttpUtilitygüvenle çerezi yazmadan önce çerez değerini kodlamak ve bunu okumaya geri özgün formuna dönüştürmek için.

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

Bu, ve işaretleri durdurur ve bir çereze yazılırken bir değer ad / değer çiftine ayıran işaretlere eşittir.


1
Sadece bir not, dahili olarak asp.net, kimlik doğrulama çerezini saklarken UrlEncode yerine hex kodlamasını kullanır. referenceource.microsoft.com # System.Web / Güvenlik /… yani url kodlamasının kesemeyeceği bazı durumlar olabilir mi?
Peter

17

Genel olarak tarayıcıya özel olduğunu düşünüyorum. Güvenli tarafta olmak için, base64 bir JSON nesnesini kodlar ve içindeki her şeyi saklar. Bu şekilde kodunu çözmeniz ve JSON'u ayrıştırmanız gerekir. Base64'te kullanılan tüm karakterler, tüm tarayıcılar olmasa da çoğu ile iyi oynamalıdır.


Bu yanıt tarayıcılar arasında tutarlı bir yanıt gibi görünüyor. Bunu saatlerce çalıştıktan sonra hızlı bir çözüm bulmaya çalıştıktan sonra fark ettim: Ben de almadım. Kendinizi güçlüklerden kurtarmak için tam olarak yukarıda önerildiği gibi yapın.
gülümse

Bunu denemedim, ancak base64 kodlama sadece ascii karakterleri ile çalıştığını söyleyerek bu konuda diğer mesajları okudum.
user984003

11

İşte mümkün olduğunca az kelimeyle . Kaçması gerekmeyen karakterlere odaklanın:

Kurabiyeler için:

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

URL'ler için

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

Çerezler ve URL'ler için (kavşak)

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

Bu şekilde cevap verirsiniz.

Çerezler için, = genellikle çerez değerini ayarlamak için kullanıldığından = kaldırıldığını unutmayın.

URL'ler için bu = tutuldu. Kesişme açıkça yoktur.

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

Özellikle son karakterlerle karşılaşırsa, çerezin çift tırnak ile sarıldığı bir Java çerez ortamında, ortaya çıkan ve beklenmedik bir şekilde ortaya çıktığı ortaya çıkıyor.

Güvende olmak için sadece A-Za-z1-9 kullanın. Ben de bunu yapacağım.


Safari Çerezler benim tek sorun tarayıcı oldu - diğer tüm tarayıcılar iyi çalıştı. Eşit = işaretler ve boşluklarla başa çıkmak için UrlEncode ve benim çerez UrlDecode gerekiyordu. Çerezdeki Base64Encode gibi. (Safari Sadece gerekli - diğer tarayıcılar kodlanmış çerez ile ve kodsuz çerez olmadan iyi çalıştı.)
Sql Surfer

Cevabınıza yol açan kaynakları listelerseniz daha iyi olur!
Loc

1
@Loc 3 saatten fazla deneme ve inceleme.
mmm

10

Nisan 2011'de yayınlanan daha yeni rfc6265 :

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 yanıtına bakarsanız , daha yeni kısıtlamaların daha katı olduğunu görürsünüz.


6

";" bir çerezin değer alanında, ayarlanacak ad ";" çoğu tarayıcıda ...


1

Çerez spesifikasyonlarının 2 sürümü vardır
1. Sürüm 0 çerezleri aka Netscape çerezleri,
2. Sürüm 1 aka RFC 2965 çerezleri
Sürüm 0'da Çerezlerin adı ve değer kısmı, noktalı virgül, virgül, eşittir işareti ve boşluk hariç karakter dizisidir. çift tırnak şekilde kullanılmadığı takdirde
sürüm 1 daha bunu kontrol edebilirsiniz karmaşık bir çok şey burada
adı değeri bölümü için bu versiyon özellikleri ise $ işareti ile başlayamaz adı dışındaki hemen hemen aynıdır


0 sürümünde değerlerin eşittir işaretini hariç tutması gerektiği nerede yazıyor?
Gili

1

IE ve Edge ile ilgili ilginç bir sorun daha var. Adları 1'den fazla süreye sahip çerezlerin sessizce bırakıldığı görülmektedir. Yani bu işe yarıyor:

cookie_name_a = DEĞERİa KESİNLİK

bu düşecek

cookie.name.a = DEĞERİa KESİNLİK


Tarayıcı davranışı çerezlerde tutarlı olmadığından çoğaltmamız için tam tarayıcı sürümünü eklerseniz harika olur.
Gerald

0

bu basit:

<cookie-name>, kontrol karakterleri (CTL'ler), boşluklar veya sekmeler dışında herhangi bir US-ASCII karakteri olabilir. Ayrıca aşağıdaki gibi bir ayırıcı karakter içermemelidir: () <> @,; : \ "/ []? = {}.

Bir <cookie değeri> isteğe bağlı olarak çift tırnak işareti olarak ayarlanabilir ve CTL'ler, boşluk, çift tırnak işaretleri, virgül, noktalı virgül ve ters eğik çizgi hariç tüm US-ASCII karakterlerine izin verilir. Kodlama: Birçok uygulama, çerez değerleri üzerinde URL kodlaması gerçekleştirir, ancak RFC belirtimi uyarınca gerekli değildir. Hangi karakterlere izin verildiğine ilişkin gereksinimleri karşılamaya yardımcı olur.

Bağlantı: https://developer.mozilla.org/tr-TR/docs/Web/HTTP/Headers/Set-Cookie#Directives


0

Bir düşünce daha. Kısa süre önce, bir PHP betiğine gönderilen ve şifreli bir çerez olarak döndürmek için gerekli olan bazı hassas verilerin, 'güvenli' olduğunu düşündüğüm tüm base64 değerlerini kullanan bir şema uyguladım. Bu yüzden, RC4 kullanarak veri öğelerini saygıyla şifreledim, koştum base64_encode aracılığıyla çıktı ve çerez siteye mutlu bir şekilde döndü. Base64 kodlu bir dize bir "+" sembolü içerene kadar test iyi gitti gibi görünüyor Dize sorunsuz bir şekilde sayfa çerezine yazılmıştır. Sonra benim PHP adlı sonraki bir sayfa ve $ _COOKIE dizisi yoluyla çerez elde zaman, dize şimdi "+" işareti eksik olduğunu bulmak için kekelendi. Bu karakterin her yerine bir ASCII alanı.

O zamandan beri bu senaryoyu açıklayan benzer kaç çözümlenmemiş şikayeti göz önünde bulundurduğumda, genellikle çerezleri rasgele verileri "güvenli bir şekilde" saklamak için base64 kullanmaya çok sayıda atıfta bulunarak, sorunu işaret ettiğimi ve kabul edilebilir kludgy çözümümü sunacağımı düşündüm.

Bir veri parçası üzerinde yapmak istediğiniz şifrelemeyi yaptıktan ve "çerez güvenli" yapmak için base64_encode kullandıktan sonra, çıktı dizesini bu şekilde çalıştırın ...

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

Burada kodlanmış değeri bir çerez olarak kullanmak için sayfaya döndürmeden önce, basitçe "+" (ve "=" karakterini) diğer "çerez güvenli" karakterleri ile değiştiriyorum. İşlenmekte olan dizenin uzunluğunun değişmediğini unutmayın. Aynı (veya sitedeki başka bir sayfa) PHP betiğimi tekrar çalıştırdığında, bu çerezi eksik karakterler olmadan kurtarabilirim. Çerezi, oluşturduğum aynı fix64 () çağrısından geçirmeyi hatırlamam gerekiyor ve oradan her zamanki base64_decode () ile kodunu çözebilir, ardından şemanızdaki diğer şifre çözme işlemlerini izleyebilirim.

PHP'de yapabileceğim, çerezlerde kullanılan base64 dizelerinin bozulmadan PHP'ye geri aktarılmasına izin veren bazı ayarlar olabilir. Bu arada bu işe yarıyor. "+" Bir "yasal" çerez değeri olabilir, ancak böyle bir dize PHP'ye geri göndermek için herhangi bir arzunuz varsa (benim durumumda $ _COOKIE dizisi aracılığıyla), kaldırmak için yeniden işleme öneririm karakterleri rahatsız edebilir ve kurtarma işleminden sonra geri yükleyebilirsiniz. Aralarından seçim yapabileceğiniz birçok "çerez güvenli" karakteri vardır.


0

Değişkenleri daha sonra kullanıyorsanız, pathaksanlı karakterlerin gerçekten geçmesine izin vereceğini, ancak aslında tarayıcı yoluyla eşleşmeyeceğini göreceksiniz. Bunun için onları KODLAMALISINIZ. Yani şöyle:

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

Yani "izin verilen" karakter, şartname ne daha fazla olabilir. Ancak, spesifikasyon içinde kalmalı ve güvende olmak için URI kodlu dizeleri kullanmalısınız.


-1

Yıllar önce MSIE 5 veya 5.5 (ve muhtemelen her ikisi de), inanabiliyorsanız HTML bloğunda "-" ile ilgili ciddi bir sorun yaşadı. Her ne kadar doğrudan ilgili olmasa da, sunucu tarafı veritabanındaki diğer her şeyi aramak için çerezde bir MD5 karma (yalnızca harf ve rakam içeren) depoladığımızdan beri.


-2

Kullanarak bitirdim

cookie_value = encodeURIComponent(my_string);

ve

my_string = decodeURIComponent(cookie_value);

Bu her tür karakter için işe yarıyor gibi görünüyor. Noktalı virgül veya virgül olmayan karakterlerde bile garip sorunlar yaşadım.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.