这个是快速的:
Cookie名称和值中允许的字符是什么?它们与URL或某些常见子集相同吗?
我问的原因是我最近发现了一些奇怪的行为,其名称中包含-
的Cookie,我只是想知道它是否是浏览器特定的或者我的代码是否有问题。
答案 0 :(得分:359)
这个是快速的:
你可能认为它应该是,但实际上它根本不存在!
Cookie名称和值中允许的字符是什么?
根据古代Netscape cookie_spec,整个NAME=VALUE
字符串是:
一系列字符,不包括分号,逗号和空格。
所以-
应该有效,而且我在这里的浏览器中似乎没问题;你在哪里遇到麻烦?
通过上述含义:
=
合法包含,但可能含糊不清。浏览器总是在字符串中的第一个=
符号上拆分名称和值,因此在实践中,您可以在VALUE中放置=
符号,但不能在NAME中放置。没有提及,因为Netscape在编写规范时非常糟糕,但似乎一直受到浏览器的支持:
NAME或VALUE可能是空字符串
如果字符串中根本没有=
符号,浏览器会将其视为具有空字符串名称的Cookie,即Set-Cookie: foo
与Set-Cookie: =foo
相同
当浏览器输出一个空名称的cookie时,它们会省略等号。因此Set-Cookie: =bar
会产生Cookie: bar
。
名称和值中的逗号和空格实际上似乎有效,但等号周围的空格被修剪
不允许控制字符(\x00
至\x1F
加\x7F
)
未提及且浏览器完全不一致的是非ASCII(Unicode)字符:
所以实际上你根本不能在cookie中使用非ASCII字符。如果你想使用Unicode,控制代码或其他任意字节序列,cookie_spec要求你使用你自己选择的ad-hoc编码方案,并建议URL编码(由JavaScript的encodeURIComponent
生成)作为一个合理的选择
就实际标准而言,已经有一些尝试编纂cookie行为,但到目前为止还没有人真正反映现实世界。
RFC 2109试图编纂和修复原始的Netscape cookie_spec。在此标准中,不允许使用更多特殊字符,因为它使用RFC 2616令牌(-
仍然允许在那里),并且只有值可以在引用中指定 - 字符串与其他字符。没有浏览器实现过限制,引用字符串和转义的特殊处理,或本规范中的新功能。
RFC 2965是另一回事,整理2109并在'版本2 cookies'方案下添加更多功能。也没有人实施任何一项。此规范与早期版本具有相同的令牌和引用字符串限制,并且同样是一堆废话。
RFC 6265是一个HTML5时代的尝试,以清理历史混乱。它仍然与现实完全不符,但它比早期的尝试要好得多 - 它至少是浏览器支持的适当子集,不会引入任何应该工作但不能工作的语法(就像之前的引用字符串一样)
在6265中,cookie名称仍被指定为RFC 2616 token
,这意味着您可以从alphanums中选择加号:
!#$%&'*+-.^_`|~
在cookie值中,它正式禁止(由浏览器过滤)控制字符和(不一致地实现的)非ASCII字符。它保留了cookie_spec对空格,逗号和分号的禁止,以及与实际实现早期RFC的任何可怜的白痴的兼容,它还禁止反斜杠和引号,除了包含整个值的引号(但在这种情况下,引号仍然被认为是值,而不是编码方案)。因此,您可以使用alphanums plus:
!#$%&'()*+-./:<=>?@[]^_`{|}~
在现实世界中,我们仍在使用原始和最差的Netscape cookie_spec,因此使用cookie的代码应该准备好遇到几乎任何东西,但是对于生成cookie的代码,建议坚持使用RFC中的子集6265。
答案 1 :(得分:28)
在ASP.Net中,您可以使用System.Web.HttpUtility
在写入cookie之前安全地对cookie值进行编码,并在读取时将其转换回原始格式。
// Encode
HttpUtility.UrlEncode(cookieData);
// Decode
HttpUtility.UrlDecode(encodedCookieData);
这会阻止符号和等号将符号分成一堆名称/值对,因为它被写入cookie。
答案 2 :(得分:17)
我认为这通常是浏览器特定的。为了安全起见,base64编码一个JSON对象,并将所有内容存储在其中。这样你只需解码它并解析JSON。如果不是所有浏览器,base64中使用的所有字符都可以正常使用。
答案 3 :(得分:9)
在这里,尽可能少的单词。专注于不需要转义的角色:
对于cookies:
abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!#$%&'()*+-./:<>?@[]^_`{|}~
对于网址
abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789.-_~!$&'()*+,;=:@
对于cookies和网址(交集)
abdefghijklmnqrstuvxyzABDEFGHIJKLMNQRSTUVXYZ0123456789!$&'()*+-.:@_~
你是怎么回答的。
请注意,对于Cookie, = 已被删除,因为它已被删除 通常用于设置cookie值。
对于网址,保留了=。交叉点显然没有。
var chars = "abdefghijklmnqrstuvxyz"; chars += chars.toUpperCase() + "0123456789" + "!$&'()*+-.:@_~";
结果发现转义仍然发生且意外发生,尤其是在Java cookie环境中,如果遇到最后一个字符,则cookie用双引号括起来。
为了安全起见,只需使用A-Za-z1-9即可。这就是我要做的事情。
答案 4 :(得分:8)
2011年4月发布的更新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 回答,您会看到更严格的新限制。
答案 5 :(得分:5)
你不能把“;”在cookie的value字段中,将设置的名称是“;”之前的字符串在大多数浏览器中...
答案 6 :(得分:1)
有两种版本的cookies规格
1.版本0 cookie又名Netscape cookie,
2.版本1又名RFC 2965 cookie
在版本0中,cookie的名称和值部分是字符序列,不包括分号,逗号,等号和空格,如果不与双引号一起使用
版本1更复杂,你可以检查它here
在此版本中,名称值部分的规格几乎相同,但名称不能以$ sign开头
答案 7 :(得分:1)
IE和Edge还有另一个有趣的问题。名称超过1个周期的Cookie似乎会被默默地删除。 所以 这有效:
cookie_name_a =值a
虽然这会被取消
cookie.name.a =值a
答案 8 :(得分:0)
很简单:
可以是除控制外的任何US-ASCII字符 字符(CTL),空格或制表符。它还不能包含 分隔符如下所示:()<> @,; :\“ / []?= {}。
可以选择用双引号和任何 US-ASCII字符,不包括CTL,空格,双引号,逗号, 允许使用分号和反斜杠。编码:许多实现 对Cookie值执行URL编码,但是不需要 RFC规范。它确实有助于满足有关以下方面的要求 但是允许使用哪些字符。
链接:https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#Directives
答案 9 :(得分:0)
再考虑一下。我最近实施了一个方案,其中一些敏感数据发布到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中进行一些设置,以允许将cookie中使用的base64字符串不损坏地传输回PHP。同时,这有效。 “ +”可能是“合法”的cookie值,但是如果您希望将这样的字符串传输回PHP(以我为例,通过$ _COOKIE数组),我建议重新处理以删除冒犯性格,并在恢复后将其还原。还有许多其他的“ cookie安全”字符可供选择。
答案 10 :(得分:0)
如果以后使用这些变量,您会发现path
之类的东西实际上会让带重音符号的字符通过,但实际上与浏览器路径不匹配。为此,您需要对它们进行URIEncode。所以就是这样:
const encodedPath = encodeURI(myPath);
document.cookie = `use_pwa=true; domain=${location.host}; path=${encodedPath};`
因此,“允许的”字符可能会超出规范中的字符。但是您应该遵守规范,并使用URI编码的字符串来保证安全。
答案 11 :(得分:-1)
多年前MSIE 5或5.5(可能两者)在HTML块中出现了一些严重的“ - ”问题,如果你能相信的话。虽然它没有直接相关,因为我们已经在cookie中存储了MD5哈希(仅包含字母和数字)以查找服务器端数据库中的所有其他内容。
答案 12 :(得分:-2)
我最终使用
view model
和
view model
这似乎适用于各种字符。否则我就遇到了奇怪的问题,即使使用的字符不是分号或逗号。