कुकीज़ में अनुमत वर्ण क्या हैं?


301

कुकी नाम और मूल्य दोनों में अनुमत वर्ण क्या हैं? क्या वे URL या कुछ सामान्य सबसेट के समान हैं?

कारण मैं पूछ रहा हूं कि मैंने हाल ही में कुकीज़ के साथ कुछ अजीब व्यवहार किया है -जो उनके नाम पर है और मैं सोच रहा हूं कि क्या यह कुछ ब्राउज़र विशिष्ट है या यदि मेरा कोड दोषपूर्ण है।

जवाबों:


391

यह एक शीघ्र है:

आपको लगता है कि यह होना चाहिए, लेकिन वास्तव में यह बिल्कुल नहीं है!

कुकी नाम और मूल्य दोनों में अनुमत वर्ण क्या हैं?

प्राचीन नेटस्केप कुकी_स्पेक के अनुसार संपूर्ण NAME=VALUEस्ट्रिंग है:

अर्ध-बृहदान्त्र, अल्पविराम और सफेद स्थान को छोड़कर पात्रों का एक क्रम।

तो -काम करना चाहिए, और यह मेरे द्वारा प्राप्त किए गए ब्राउज़रों में ठीक प्रतीत होता है; आप इससे परेशान कहाँ हैं?

उपरोक्त के निहितार्थ द्वारा:

  • =शामिल करने के लिए कानूनी है, लेकिन संभावित रूप से अस्पष्ट है। ब्राउज़र हमेशा =स्ट्रिंग में पहले प्रतीक पर नाम और मूल्य को विभाजित करते हैं , इसलिए व्यवहार में आप =VALUE में एक प्रतीक रख सकते हैं लेकिन NAME नहीं।

उल्लेख नहीं किया गया है, क्योंकि नेटस्केप चश्मा लिखने में भयानक थे, लेकिन लगता है कि वे लगातार ब्राउज़र द्वारा समर्थित हैं:

  • या तो NAME या VALUE रिक्त स्ट्रिंग्स हो सकता है

  • यदि =स्ट्रिंग में कोई प्रतीक नहीं है , तो ब्राउज़र इसे खाली-स्ट्रिंग नाम के साथ कुकी के रूप में मानते हैं, अर्थात Set-Cookie: fooजैसा है Set-Cookie: =foo

  • जब ब्राउज़र एक खाली नाम के साथ कुकी का उत्पादन करते हैं, तो वे बराबर चिह्न को छोड़ देते हैं। इसलिए Set-Cookie: =barभूल जाते हैं Cookie: bar

  • अल्पविराम और नाम और मूल्यों में रिक्त स्थान वास्तव में काम करने लगते हैं, हालांकि बराबर चिह्न के चारों ओर रिक्त स्थान को छंटनी की जाती है

  • (नियंत्रण वर्ण \x00के लिए \x1Fप्लस \x7F) की अनुमति नहीं है

क्या उल्लेख नहीं है और ब्राउज़र पूरी तरह से असंगत हैं, गैर- ASCII (यूनिकोड) वर्ण हैं:

  • ओपेरा और गूगल क्रोम में, वे UTF-8 के साथ कुकी हेडर के लिए एन्कोडेड हैं;
  • IE में, मशीन के डिफ़ॉल्ट कोड पृष्ठ का उपयोग किया जाता है (स्थानीय-विशिष्ट और कभी भी UTF-8);
  • फ़ायरफ़ॉक्स (और अन्य मोज़िला-आधारित ब्राउज़र) प्रत्येक UTF-16 कोड बिंदु के कम बाइट का उपयोग अपने दम पर करते हैं (इसलिए ISO-8859-1 ठीक है, लेकिन कुछ भी अन्य काम है);
  • सफारी बस किसी भी कुकी को गैर-एएससीआईआई पात्रों को भेजने से इनकार करती है।

तो व्यवहार में आप कुकीज़ में गैर- ASCII वर्णों का उपयोग नहीं कर सकते। यदि आप यूनिकोड, नियंत्रण कोड या अन्य मनमाने ढंग से बाइट अनुक्रमों का उपयोग करना चाहते हैं, तो कुकी_स्पेक आपकी स्वयं की चुनने की एक तदर्थ एन्कोडिंग योजना का उपयोग करता है और encodeURIComponentएक उचित विकल्प के रूप में यूआरएल-एन्कोडिंग (जावास्क्रिप्ट द्वारा निर्मित ) का सुझाव देता है ।

वास्तविक मानकों के संदर्भ में , कुकी व्यवहार को संहिताबद्ध करने के लिए कुछ प्रयास किए गए हैं, लेकिन वास्तव में वास्तव में वास्तविक दुनिया को प्रतिबिंबित नहीं करता है।

  • RFC 2109 मूल नेटस्केप कुकी_स्पेक को संहिताबद्ध और ठीक करने का एक प्रयास था। इस मानक में कई और विशेष वर्णों को अस्वीकृत कर दिया जाता है, क्योंकि यह RFC 2616 टोकन का उपयोग करता है ( -यह अभी भी वहां अनुमति है), और अन्य वर्णों के साथ एक उद्धृत-स्ट्रिंग में केवल मान निर्दिष्ट किया जा सकता है। किसी भी ब्राउज़र ने कभी भी सीमाओं को लागू नहीं किया, उद्धृत स्ट्रिंग्स और भागने की विशेष हैंडलिंग या इस विशेषता में नई विशेषताएं।

  • RFC 2965 इस पर एक और चल रहा था, 2109 तक टिक गया और 'वर्जन 2 कुकीज' स्कीम के तहत और फीचर्स जोड़े। किसी ने कभी भी उस पर कोई अमल नहीं किया। इस युक्ति में पहले संस्करण के समान टोकन-और-उद्धृत-स्ट्रिंग सीमाएँ हैं और यह केवल बकवास का अधिक भार है।

  • RFC 6265 ऐतिहासिक गड़बड़ को साफ करने के लिए HTML5-युग का प्रयास है। यह अभी भी वास्तविकता से बिल्कुल मेल नहीं खाता है, लेकिन यह बहुत बेहतर है, फिर पहले का प्रयास-यह कम से कम एक ब्राउज़र का समर्थन करता है, जो किसी भी वाक्यविन्यास को पेश करने का समर्थन नहीं करता है, जो काम करने वाला है लेकिन (पिछले उद्धृत-स्ट्रिंग की तरह) नहीं ।

6265 में कुकी का नाम अभी भी RFC 2616 के रूप में निर्दिष्ट है token, जिसका अर्थ है कि आप अल्फ़ान्यूम्स प्लस से चुन सकते हैं:

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

कुकी मान में यह औपचारिक रूप से (ब्राउज़रों द्वारा फ़िल्टर किया गया) नियंत्रण वर्ण और (असंगत रूप से कार्यान्वित) गैर-ASCII वर्णों पर प्रतिबंध लगाता है। यह अंतरिक्ष, कॉमा और अर्धविराम पर कुकी_स्पेक के निषेध को बरकरार रखता है, साथ ही किसी भी गरीब बेवकूफों के साथ संगतता के लिए जो वास्तव में पहले के RFC को लागू करते थे, इसने बैकस्लैश और उद्धरणों पर प्रतिबंध लगा दिया था, उद्धरणों के अलावा पूरे मूल्य को लपेटते हुए (लेकिन उस स्थिति में उद्धरण अभी भी भाग माना जाता है। मूल्य, एन्कोडिंग योजना नहीं)। ताकि आपको अल्फ़ान्यूम्स के साथ छोड़ दिया जाए:

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

वास्तविक दुनिया में हम अभी भी मूल-और सबसे खराब नेटस्केप कुकी_स्पेक का उपयोग कर रहे हैं, इसलिए कुकीज़ का सेवन करने वाले कोड को बहुत अधिक कुछ भी तैयार करने के लिए तैयार किया जाना चाहिए, लेकिन कुकीज़ का उत्पादन करने वाले कोड के लिए आरएफसी 6265 में सबसेट के साथ रहना उचित है।


@bobince क्या आपका मतलब है कि आरएफसी में कहा गया है कि कुकी मूल्यों में ;चरित्र तब तक हो सकता है जब तक वह दोहरे उद्धरणों से घिरा हो? जैसे:Set-Cookie: Name=Va";"lue; Max-Age=3600
पचेरियर

@ स्पेसर: पूरे मूल्य को एक उद्धृत-स्ट्रिंग होना होगा, इसलिए यह होना चाहिए Name="Va;lue"; max-age...। यह ब्राउज़रों में काम नहीं करता है और इसे RFC 6265 में अनुमति नहीं है, जो 2965 को बदलने का प्रस्ताव है और वास्तविकता को थोड़ा बेहतर दिखाने की कोशिश करता है।
बॉबी

@bobince - मुझे पता है कि यह पुराना है, लेकिन क्या मैं आपका जवाब सही ढंग से पढ़ रहा हूं इसका मतलब यह है कि कुकी मानों में तकनीकी रूप से रिक्त स्थान की अनुमति नहीं है? "अर्ध-बृहदान्त्र, अल्पविराम और सफेद स्थान को छोड़कर " [जोर मेरा]
एडम रैकिस

1
@ एडडम: हाँ, यदि आप नेटस्केप स्पेक या आरएफसी 6265 से जा रहे हैं, तो व्हाईटस्पेस को कच्चे (अन-डॉकॉट) कुकी मूल्य में अनुमति नहीं है। यह मेरे द्वारा आजमाए गए ब्राउज़रों में काम नहीं करता है, लेकिन मैं इस पर भरोसा नहीं करूंगा।
बॉब

2
आरएफसी 6265 परिभाषित करता है के रूप में टोकन 1*<any CHAR except CTLs or separators>और विभाजक हैं (, ), <, >, @, ,, ;, :, \, ", /, [, ], ?, =, {, }, SPऔर HT, इसलिए कुकी नाम alphanums होना चाहिए प्लस!#$%&'*+-.?^_`|~
गण क्वान

28

ASP.Net में आप System.Web.HttpUtilityकुकी को लिखने से पहले कुकी मान को सुरक्षित रूप से एनकोड करने के लिए उपयोग कर सकते हैं और इसे बाहर पढ़ने पर अपने मूल रूप में बदल सकते हैं।

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

यह एम्परसैंड्स को रोक देगा और नाम / मूल्य जोड़े के एक गुच्छा में एक मूल्य को विभाजित करने वाले संकेतों के बराबर होता है क्योंकि यह एक कुकी के लिए लिखा जाता है।


1
बस एक नोट, आंतरिक रूप से asp.net प्रमाणीकरण कुकी संग्रहीत करते समय UrlEncode के बजाय हेक्स एन्कोडिंग का उपयोग करता है। referenceource.microsoft.com # System.Web / Security /… तो कुछ ऐसे मामले हो सकते हैं जहाँ url एनकोड वॉन्ट कट नहीं करेगा?
पीटर

17

मुझे लगता है कि यह आम तौर पर विशिष्ट ब्राउज़र है। सुरक्षित पक्ष पर होने के लिए, बेस 64 एक JSON ऑब्जेक्ट को एनकोड करता है, और उसमें सब कुछ स्टोर करता है। इस तरह से आपको बस इसे डिकोड करना होगा और JSON को पार्स करना होगा। बेस 64 में उपयोग किए जाने वाले सभी वर्णों को ठीक से खेलना चाहिए, यदि सभी ब्राउज़र नहीं।


यह उत्तर ब्राउज़रों के अनुरूप है। मुझे इसका एहसास हुआ कि कई घंटे काम करने के बाद त्वरित समाधान पाने की कोशिश की गई: मुझे एक भी नहीं मिला। बस के रूप में खुद को बाधाओं को बचाने के लिए ऊपर की सिफारिश की है।
मुस्कान

यह कोशिश नहीं की, लेकिन मैंने इस बारे में अन्य पोस्ट पढ़ते हुए कहा कि base64 एनकोड केवल ascii वर्णों के साथ काम करता है।
15:

11

यहाँ यह संभव के रूप में कुछ शब्दों में है । ऐसे चरित्रों पर ध्यान केंद्रित करें, जिनसे बचने की आवश्यकता नहीं है:

कुकीज़ के लिए:

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

Urls के लिए

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

कुकीज़ और urls (प्रतिच्छेदन) के लिए

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

इसी तरह आप जवाब दें।

ध्यान दें कि कुकीज़ के लिए, = को हटा दिया गया है क्योंकि यह आमतौर पर कुकी मान को सेट करने के लिए उपयोग किया जाता है।

Urls के लिए यह = रखा गया था। चौराहे स्पष्ट रूप से बिना है।

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

बाहर निकलना अभी भी घटता है और अप्रत्याशित रूप से घटित होता है, विशेष रूप से जावा कुकी वातावरण में जहां कुकी दोहरे उद्धरणों के साथ लिपटी होती है यदि यह अंतिम पात्रों का सामना करती है।

इसलिए सुरक्षित रहने के लिए, बस A-Za-z1-9 का उपयोग करें। यही मैं करने जा रहा हूं।


सफारी कुकीज़ मेरी एकमात्र समस्या ब्राउज़र थी - अन्य सभी ब्राउज़रों ने ठीक काम किया। मैं समान और संकेत और रिक्त स्थान से निपटने के लिए अपनी कुकी UrlEncode और UrlDecode करता था। कुकी में Base64Encode की तरह। (सफ़ारी केवल इसके लिए आवश्यक है- अन्य ब्राउज़रों ने एन्कोडेड कुकी के साथ और उसके बिना ठीक काम किया।)
Sql Surfer

यह बेहतर है यदि आप सूचीबद्ध करते हैं कि आपके उत्तर के लिए कौन से स्रोत हैं!
लोक

1
@ 3 घंटे से अधिक परीक्षण और निरीक्षण।
mmm

10

अप्रैल 2011 में प्रकाशित नए 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 उत्तर को देखते हैं तो आप देखते हैं कि नए प्रतिबंध अधिक सख्त हैं।


6

आप नहीं डाल सकते हैं "" कुकी के मूल्य क्षेत्र में, जो नाम सेट किया जाएगा वह स्ट्रिंग है जब तक ";" अधिकांश ब्राउज़रों में ...


1

कुकीज़ विनिर्देशों के 2 संस्करण हैं
। संस्करण 0 कुकीज़ उर्फ ​​नेटस्केप कुकीज़,
2. संस्करण 1 उर्फ ​​आरएफसी 2965 कुकीज़
संस्करण 0 में कुकीज़ के नाम और मूल्य भाग अर्धविराम, अल्पविराम, विषुव चिह्न, और व्हाट्सएप को छोड़कर पात्रों के अनुक्रम हैं। , अगर दोहरे उद्धरण चिह्नों के साथ उपयोग नहीं किया जाता है तो
1 बहुत अधिक जटिल है आप इसे यहाँ देख सकते हैं
। इस संस्करण में नाम मान भाग के लिए चश्मा लगभग समान है सिवाय नाम $ संकेत के साथ शुरू नहीं हो सकता है


यह कहां कहता है कि मानों को संस्करण 0 में बराबरी के संकेत को छोड़ना होगा?
गिली

1

आईई और एज के साथ एक और दिलचस्प मुद्दा है। 1 से अधिक अवधि वाले नाम वाले कुकीज़ चुपचाप गिराए गए प्रतीत होते हैं। तो यह काम करता है:

cookie_name_a = valuea

जबकि यह गिरा दिया जाएगा

cookie.name.a = valuea


बहुत अच्छा होगा यदि आप हमें दोहराने के लिए सटीक ब्राउज़र संस्करण जोड़ते हैं, क्योंकि ब्राउज़र व्यवहार कुकीज़ पर संगत नहीं है।
गेराल्ड

0

यह आसान है:

A <कुकी-नाम> नियंत्रण वर्ण (CTL), रिक्त स्थान, या टैब को छोड़कर कोई भी US-ASCII वर्ण हो सकता है। इसमें निम्नलिखित की तरह एक विभाजक वर्ण नहीं होना चाहिए: () <> @,; : \ "/ []? = {}।

एक <कुकी-मूल्य> वैकल्पिक रूप से दोहरे उद्धरण चिह्नों में सेट किया जा सकता है और सीटीएल, व्हाट्सएप, डबल उद्धरण, अल्पविराम, अर्धविराम और बैकस्लैश को छोड़कर किसी भी यूएस-एएससीआईआई पात्रों की अनुमति है। एन्कोडिंग: कई कार्यान्वयन कुकी मानों पर URL एन्कोडिंग करते हैं, हालांकि यह RFC विनिर्देशन के अनुसार आवश्यक नहीं है। यह उन आवश्यकताओं को संतुष्ट करने में मदद करता है जिनके बारे में पात्रों की अनुमति है।

लिंक: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives


0

एक और विचार। मैंने हाल ही में एक योजना लागू की है जिसमें एक PHP स्क्रिप्ट में पोस्ट किए गए कुछ संवेदनशील डेटा को एन्क्रिप्टेड कुकी के रूप में परिवर्तित करने और वापस करने के लिए आवश्यक है, जिसका उपयोग मैंने सोचा था कि सभी बेस 64 मानों का उपयोग 'सुरक्षित' की गारंटी है। इसलिए मैंने RC4 का उपयोग करके डेटा आइटमों को सावधानी से एन्क्रिप्ट किया। base64_encode के माध्यम से आउटपुट, और खुशी से कुकी को साइट पर लौटाया गया। परीक्षण तब तक अच्छा लग रहा था जब तक कि एक base64 एन्कोडेड स्ट्रिंग में "+" प्रतीक नहीं था। स्ट्रिंग को पेज कुकी को बिना किसी परेशानी के लिखा गया था। ब्राउज़र डायग्नोस्टिक का उपयोग करके मैं भी कर सकता था। सत्यापित करें कि कुकीज़ अपरिवर्तित लिखी गई थी। फिर जब एक बाद वाले पृष्ठ ने मेरे PHP को कॉल किया और $ _COOKIE सरणी के माध्यम से कुकी प्राप्त की, तो मुझे यह पता लगाने के लिए हतोत्साहित किया गया था कि स्ट्रिंग अब "+" चिन्ह को याद नहीं कर रही है। ASCII स्थान।

यह देखते हुए कि मैंने तब से इस परिदृश्य का वर्णन करते हुए कितनी समान अनसुलझे शिकायतों को देखा है, अक्सर कुकीज़ में मनमाने ढंग से डेटा को "सुरक्षित रूप से" स्टोर करने के लिए कई संदर्भों का उपयोग करते हुए, मैंने सोचा कि मैं इस समस्या को इंगित करता हूं और अपने कोडली कुडली समाधान की पेशकश करता हूं।

आपके द्वारा डेटा के एक टुकड़े पर जो भी एन्क्रिप्शन करना चाहते हैं, उसे करने के बाद, और फिर "कुकी-सुरक्षित" बनाने के लिए बेस 64_encode का उपयोग किया, इसके माध्यम से आउटपुट स्ट्रिंग चलाएं ...

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

यहाँ मैं केवल "+" (और मैंने तय किया "=") के साथ ही अन्य "कुकी सुरक्षित" पात्रों के साथ, पृष्ठ पर एन्कोडेड मान को कुकी के रूप में उपयोग करने से पहले। ध्यान दें कि संसाधित की जा रही स्ट्रिंग की लंबाई नहीं बदलती है। जब वही (या साइट पर कोई अन्य पृष्ठ) मेरी PHP स्क्रिप्ट को फिर से चलाता है, तो मैं इस कुकी को लापता पात्रों के बिना पुनर्प्राप्त कर पाऊंगा। मुझे सिर्फ कुकी को उसी फिक्स 64 () कॉल मी के माध्यम से वापस पास करना याद रखना है, और वहां से मैं इसे सामान्य बेस 64_डब्लू () के साथ डिकोड कर सकता हूं, इसके बाद आपकी योजना में जो भी डिक्रिप्शन है।

कुछ सेटिंग हो सकती हैं जिन्हें मैं PHP में बना सकता हूं जो कुकीज़ में इस्तेमाल किए गए आधार 64 स्ट्रिंग्स को बिना भ्रष्टाचार के PHP में वापस स्थानांतरित करने की अनुमति देता है। इस बीच में यह काम करता है। "+" एक "कानूनी" कुकी मूल्य हो सकता है, लेकिन अगर आपको पीएचपी (मेरे मामले में $ _COOKIE सरणी के माध्यम से) इस तरह के एक स्ट्रिंग को PHP में स्थानांतरित करने में सक्षम होने की कोई इच्छा है, तो मैं हटाने के लिए पुन: प्रसंस्करण का सुझाव दे रहा हूं अपमानजनक चरित्र, और पुनर्प्राप्ति के बाद उन्हें पुनर्स्थापित करें। चुनने के लिए बहुत सारे अन्य "कुकी सुरक्षित" अक्षर हैं।


0

यदि आप बाद में चर का उपयोग कर रहे हैं, तो आप पाएंगे कि सामान pathवास्तव में उच्चारण पात्रों को जाने देगा, लेकिन यह वास्तव में ब्राउज़र पथ से मेल नहीं खाएगा। इसके लिए आपको उन्हें URIEncode करना होगा। तो इस तरह से:

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

तो "अनुमत" वर्ण, क्या कल्पना में है की तुलना में अधिक हो सकता है। लेकिन आपको कल्पना के भीतर रहना चाहिए, और सुरक्षित रहने के लिए यूआरआई-एन्कोडेड स्ट्रिंग्स का उपयोग करना चाहिए।


-1

सालों पहले MSIE 5 या 5.5 (और शायद दोनों) में HTML ब्लॉक में "-" के साथ कुछ गंभीर समस्या थी अगर आप इस पर विश्वास कर सकते हैं। यह सीधे तौर पर संबंधित नहीं है, जब से हमने कुकी में एमडी 5 हैश (केवल अक्षरों और संख्याओं सहित) संग्रहीत किया है, सर्वर-साइड डेटाबेस में सब कुछ देखने के लिए।


-2

मैंने उपयोग करना समाप्त कर दिया

cookie_value = encodeURIComponent(my_string);

तथा

my_string = decodeURIComponent(cookie_value);

यह सभी प्रकार के पात्रों के लिए काम करने लगता है। मेरे पास अजीब मुद्दे थे अन्यथा, यहां तक ​​कि उन पात्रों के साथ भी जो अर्धविराम या अल्पविराम नहीं थे।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.