【问题标题】:What are allowed characters in cookies?cookie 中允许使用哪些字符?
【发布时间】:2010-12-30 11:11:31
【问题描述】:

cookie 名称和值中允许使用哪些字符?它们与 URL 相同还是某些公共子集?

我问的原因是我最近遇到了一些奇怪的行为,cookie 的名称中包含 -,我只是想知道这是浏览器特定的东西还是我的代码有问题。

【问题讨论】:

标签: cookies


【解决方案1】:

我认为它通常是特定于浏览器的。为了安全起见,base64 对 JSON 对象进行编码,并将所有内容存储在其中。这样,您只需对其进行解码并解析 JSON。 base64 中使用的所有字符都应该在大多数浏览器(如果不是所有浏览器)上都能正常播放。

【讨论】:

  • 这个答案似乎是跨浏览器的一致答案。在工作了好几个小时试图找到一个快速的解决方案后,我意识到了这一点:我也没有得到一个。只需按照上面的建议进行操作即可省去麻烦。
  • 没试过这个,但我读过其他关于这个的帖子说base64编码只适用于ascii字符。
【解决方案2】:

有 2 个版本的 cookie 规范
1. 版本 0 cookie 又名 Netscape cookie,
2. 版本 1 又名 RFC 2965 cookie
在版本 0 中,cookie 的名称和值部分是字符序列,不包括分号、逗号、等号和空格,如果不与双引号一起使用
版本 1 要复杂得多,您可以查看它here
在此版本中,名称值部分的规范几乎相同,只是名称不能以 $ 符号开头

【讨论】:

  • 在哪里说值必须排除版本 0 中的等号?
【解决方案3】:

这个很快:

你可能认为它应该是,但实际上根本不是!

cookie 名称和值中允许使用哪些字符?

根据古代网景cookie_spec整个NAME=VALUE字符串是:

不包括分号、逗号和空格的字符序列。

所以- 应该可以工作,而且在我这里的浏览器中似乎还可以;你是哪里出了问题?

综上所述:

  • = 包含在内是合法的,但可能不明确。浏览器总是在字符串中的第一个 = 符号上拆分名称和值,因此实际上您可以将 = 符号放在 VALUE 而不是 NAME 中。

没有提到什么,因为 Netscape 在编写规范方面很糟糕,但似乎一直受到浏览器的支持:

  • NAME 或 VALUE 可能是空字符串

  • 如果字符串中根本没有=符号,浏览器会将其视为具有空字符串名称的cookie,即Set-Cookie: fooSet-Cookie: =foo相同。

  • 当浏览器输出一个空名称的 cookie 时,它​​们会省略等号。所以Set-Cookie: =bar 产生Cookie: bar

  • 名称和值中的逗号和空格似乎确实有效,但等号周围的空格被修剪了

  • 不允许使用控制字符(\x00\x1F 加上 \x7F

没有提到和浏览器完全不一致的是非 ASCII (Unicode) 字符:

  • 在 Opera 和 Google Chrome 中,它们使用 UTF-8 编码为 Cookie 标头;
  • 在 IE 中,使用机器的默认代码页(特定于语言环境,从不使用 UTF-8);
  • Firefox(和其他基于 Mozilla 的浏览器)单独使用每个 UTF-16 代码点的低字节(因此 ISO-8859-1 可以,但其他任何内容都会被破坏);
  • Safari 只是拒绝发送任何包含非 ASCII 字符的 cookie。

所以实际上你根本不能在 cookie 中使用非 ASCII 字符。如果您想使用 Unicode、控制代码或其他任意字节序列,cookie_spec 要求您使用自己选择的特殊编码方案并建议 URL 编码(由 JavaScript 的encodeURIComponent 生成)作为合理的选择。

实际标准而言,已经有一些尝试对 cookie 行为进行编码,但迄今为止没有一个真正反映现实世界。

  • RFC 2109 试图编纂和修复原始的 Netscape cookie_spec。在此标准中,不允许使用更多特殊字符,因为它使用 RFC 2616 标记(- 仍然允许在那里),并且只能在带引号的字符串中指定值和其他字符.没有浏览器实现过限制、引用字符串的特殊处理和转义,或本规范中的新功能。

  • RFC 2965 是另一个尝试,整理 2109 并在“版本 2 cookie”方案下添加更多功能。也没有人实施过任何一个。该规范与早期版本具有相同的标记和引用字符串限制,并且同样是一堆废话。

  • RFC 6265 是 HTML5 时代试图清理历史混乱的尝试。它仍然不完全符合现实,但它比早期的尝试要好得多——它至少是浏览器支持的一个适当的子集,没有引入任何应该工作但不工作的语法(如前面的引用字符串) .

在 6265 中,cookie 名称仍指定为 RFC 2616 token,这意味着您可以从字母加号中进行选择:

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

在 cookie 值中,它正式禁止(由浏览器过滤)控制字符和(不一致实现的)非 ASCII 字符。它保留了 cookie_spec 对空格、逗号和分号的禁止,并且为了与任何实际实施早期 RFC 的可怜的白痴兼容,它还禁止反斜杠和引号,除了引号包裹整个值(但在这种情况下,引号仍然被认为是值,而不是编码方案)。这样就剩下字母加号了:

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

在现实世界中,我们仍在使用原始和最差的 Netscape cookie_spec,因此使用 cookie 的代码应该准备好遇到几乎任何事情,但是对于产生 cookie 的代码,建议坚持使用 RFC 中的子集6265.

【讨论】:

  • @bobince 你的意思是说 RFC 规定 cookie 值可以有 ; 字符,只要它被双引号括起来?比如:Set-Cookie: Name=Va";"lue; Max-Age=3600
  • @Pacerier:整个值必须是带引号的字符串,所以它必须是 Name="Va;lue"; max-age...。它在浏览器中不起作用,并且在 RFC 6265 中是不允许的,它被提议替换 2965 并试图更好地反映现实。
  • @bobince - 我知道这很旧,但我是否正确阅读了您的答案,是否意味着 cookie 值中在技术上不允许使用空格? "不包括分号、逗号和空格" [强调我的]
  • @Adam:是的,如果您遵循 Netscape 规范或 RFC 6265,则在原始(未 DQUOTEd)cookie 值中不允许使用空格。它仍然在我尝试过的浏览器中工作,但我不会依赖它。
  • RFC 6265 将标记定义为1*&lt;any CHAR except CTLs or separators&gt;,分隔符为()&lt;&gt;@,;; @,\"/[]?={}HT,所以HT的cookie名称应该是是字母加!#$%&amp;'*+-.?^_`|~
【解决方案4】:

在 ASP.Net 中,您可以使用 System.Web.HttpUtility 在写入 cookie 之前安全地对 cookie 值进行编码,并在读出时将其转换回其原始形式。

// Encode
HttpUtility.UrlEncode(cookieData);

// Decode
HttpUtility.UrlDecode(encodedCookieData);

这将阻止 & 和等号在将值写入 cookie 时将其拆分为一组名称/值对。

【讨论】:

【解决方案5】:

几年前,如果您相信的话,MSIE 5 或 5.5(可能两者都有)在 HTML 块中出现了一些严重的问题,即“-”。虽然它不是直接相关的,但自从我们在 cookie 中存储了一个 MD5 哈希(仅包含字母和数字)以查找服务器端数据库中的所有其他内容之后。

【讨论】:

    【解决方案6】:

    你不能放“;”在 cookie 的 value 字段中,将设置的名称是字符串,直到 ";"在大多数浏览器中...

    【讨论】:

      【解决方案7】:

      较新的rfc6265 于 2011 年 4 月发布:

      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 的回答,您会发现新的限制更加严格。

      【讨论】:

      • 您在上面复制的轨道图中的勘误表以及第 5.4 节中的文字...该图以; OWS 分隔,文字需要文字; (带空格)。
      【解决方案8】:

      IE 和 Edge 还有一个有趣的问题。名称超过 1 个句点的 Cookie 似乎会被默默删除。 所以 这有效:

      cookie_name_a=值a

      虽然这将被删除

      cookie.name.a=值a

      【讨论】:

      • 如果您添加确切的浏览器版本以便我们复制,那就太好了,因为浏览器的行为在 cookie 上并不一致。
      • cookie-name-a = valueA 怎么样?
      【解决方案9】:

      就是这样,用尽可能少的文字。专注于不需要转义的字符:

      对于 cookie:

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

      对于网址

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

      对于cookies和url(交集)

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

      这就是你的回答。

      请注意,对于 cookie,= 已被删除,因为它是 通常用于设置cookie值。

      对于 url,这个 = 被保留。十字路口显然没有。

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

      结果转义仍在发生和意外发生,尤其是在 Java cookie 环境中,如果 cookie 遇到最后一个字符,则用双引号括起来。

      为了安全起见,请使用 A-Za-z1-9。这就是我要做的。

      【讨论】:

      • Safari Cookies 是我唯一有问题的浏览器——所有其他浏览器都运行良好。我必须对我的 cookie 进行 UrlEncode 和 UrlDecode 来处理等号 = 符号和空格。就像 Cookie 中的 Base64Encode。 (Safari 只需要这个 - 其他浏览器在有和没有编码 cookie 的情况下都可以正常工作。)
      • 最好列出导致答案的来源!
      • @Loc 超过 3 小时的试用和检查。
      【解决方案10】:

      这很简单:

      可以是除控制以外的任何 US-ASCII 字符 字符 (CTL)、空格或制表符。它也不得包含 分隔符如下: ( ) @ , ; : \ " / [ ] ? = { }。

      可以选择用双引号和任何 US-ASCII 字符,不包括 CTL、空格、双引号、逗号、 允许使用分号和反斜杠。编码:许多实现 对 cookie 值执行 URL 编码,但不是必须的 RFC 规范。它确实有助于满足关于 但是允许使用哪些字符。

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

      【讨论】:

        【解决方案11】:

        还有一个考虑因素。我最近实施了一个方案,其中发布到 PHP 脚本的一些敏感数据需要转换并作为加密 cookie 返回,它使用了我认为可以保证“安全”的所有 base64 值。所以我尽职尽责地使用 RC4 加密数据项,运行通过base64_encode输出,并愉快地将cookie返回到站点。测试似乎进展顺利,直到base64编码的字符串包含一个“+”符号。字符串被写入页面cookie没有问题。使用浏览器诊断我也可以验证 cookie 是否未更改。然后当后续页面调用我的 PHP 并通过 $_COOKIE 数组获取 cookie 时,我结结巴巴地发现字符串现在缺少“+”号。该字符的每次出现都被替换为ASCII 空格。

        考虑到从那时起我读过多少类似的未解决的投诉来描述这种情况,经常引用大量使用 base64 来“安全地”在 cookie 中存储任意数据的引用,我想我会指出问题并提供我公认的笨拙解决方案。

        在您对一段数据进行任何加密后,然后使用 base64_encode 使其“cookie-safe”,通过此运行输出字符串...

        // 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 而不会丢失字符。我只需要记住通过我创建的同一个 fix64() 调用将 cookie 传回,然后我可以使用通常的 base64_decode() 对其进行解码,然后在您的方案中进行任何其他解密。

        我可以在 PHP 中进行一些设置,允许将 cookie 中使用的 base64 字符串传输回 PHP 而不会损坏。与此同时,这有效。 “+”可能是“合法”的 cookie 值,但如果您希望能够将这样的字符串传输回 PHP(在我的情况下是通过 $_COOKIE 数组),我建议重新处理以删除冒犯的角色,并在恢复后恢复它们。还有许多其他“cookie 安全”字符可供选择。

        【讨论】:

          【解决方案12】:

          我最终使用了

          cookie_value = encodeURIComponent(my_string);
          

          my_string = decodeURIComponent(cookie_value);
          

          这似乎适用于所有类型的角色。否则我会遇到奇怪的问题,即使字符不是分号或逗号。

          【讨论】:

            【解决方案13】:

            如果你稍后使用变量,你会发现像path 这样的东西实际上会让重音字符通过,但它实际上与浏览器路径不匹配。为此,您需要对它们进行 URIEncode。所以就像这样:

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

            所以“允许”的字符可能比规范中的更多。但是您应该遵守规范,并使用 URI 编码的字符串以确保安全。

            【讨论】:

              猜你喜欢
              • 2011-10-30
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-02-07
              • 2011-06-15
              • 2013-11-15
              • 2016-05-05
              相关资源
              最近更新 更多