一个cookie的名称是否区分大小写?

50

一个HTTP Cookie由名称-值对组成,可以通过此响应由服务器设置:

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: name=value
Set-Cookie: name2=value2; Expires=Wed, 09 Jun 2021 10:18:14 GMT

接下来客户端的未来请求会是这个样子:

GET /spec.html HTTP/1.1
Host: www.example.org
Cookie: name=value; name2=value2

cookie名称区分大小写吗?

例如,如果我的服务器发送这样的响应:

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: Aaaa=Bbbb
Set-Cookie: aAaa=bBbb
Set-Cookie: aaAa=bbBb
Set-Cookie: aaaA=bbbB

期望客户端(如Chrome、FireFox、Safari、IExplorer、Opera等)在未来的请求中发送包含头部Cookie: Aaaa=Bbbb; aAaa=bBbb; aaAa=bbBb; aaaA=bbbB;的请求,这是否合理?

注意:该问题不特定于JSP、PHP或ASP。


3
@lanzz,RFC并不总是那么清晰明了……所以询问问题以确认其一致性是个好主意。不仅如此,我们可以看到下面有一个回答引用了MSDN,并陈述了cookie名称不区分大小写的句子! - Alexis Wilke
2
@AlexisWilke 我同意RFC有时候会比较模糊,但大多数情况下它们都很易读且简明扼要。OP没有提供任何阅读RFC的证据,更不用说被它搞糊涂了。MSDN并不是HTTP cookies的权威来源。 - lanzz
5个回答

49

Cookie名称区分大小写。虽然RFC没有明确说明这一点,但每个不区分大小写的比较都是明确说明的,并且关于cookie名称没有这样明确的声明。Chrome和Firefox都将cookie视为区分大小写,并保留所有大小写变体作为不同的cookie。

测试用例(PHP):

print_r($_COOKIE);

setcookie('foo', '123');
setcookie('Foo', '456');

在两次加载脚本时,观察第二次运行时$_COOKIE的输出结果。


1
@PeerStritzinger,我不确定你的评论是什么意思,或者你根本没有看过我的答案。我在RFC中找不到明确的陈述,但我对它的解释与你所说的完全相同:cookie名称区分大小写。如果你在RFC中找到了关于这个问题的明确声明,欢迎分享你的发现,但我觉得你对我的回答进行了贬低并声称它是错误的,然后你又赞同了它,这让我感到很冒犯。 - lanzz
6
@Pacerier引用了一个已经过时的RFC。RFC 2109已经被RFC 2965所取代,而RFC 2965又被RFC 6265所取代。 - lanzz
1
@Pacerier 我的意思是现在它们不再是“不区分大小写”的了。旧的 RFC 描述了它们使用与属性名相同的规则,这些规则是不区分大小写的;当前的 RFC 没有以相同的方式定义它们,并且没有明确指出 cookie 名称是不区分大小写的。使用我的示例 PHP 代码可以轻松地在 Chrome 和 Firefox 中演示区分大小写;由于两个主要浏览器将它们视为区分大小写,您别无选择,只能确保您将它们视为区分大小写,否则就会破坏与 FF 和 Chrome 的兼容性。 - lanzz
2
完全不相关RFC说了什么!我们编写的代码是要在今天使用的浏览器上运行:IE,Firefox,Chrome。由于我们的代码必须正常工作,所以我们只需要关心浏览器的实现方式。我可以告诉你至少Internet Explorer是区分大小写的,因此我们应该将cookie视为区分大小写以避免问题! - Elmue
6
你是否已经阅读了我的答案? 所有主要的浏览器都以大小写敏感的方式处理cookie名称,因为RFC规定了这样做。 你是在告诉我RFC无关紧要吗?因为你发现至少Internet Explorer实际上遵循它?更不用说如果你的代码以大小写敏感的方式处理cookie,那么浏览器也这样做就没关系了;但是如果你以大小写不敏感的方式处理它们,而浏览器对大小写敏感,则情况就不同了。 - lanzz
显示剩余3条评论

7
在底部有一个脚本,演示了浏览器和 .Net 框架中 Cookie 的大小写敏感性。每次运行它,都会插入一个名为 xxxxxxxxxx 的 Cookie,其中包含随机的大/小写字母。按 F5 刷新几次,可以插入几个 Cookies。
我已在 Chrome 和 Firefox 上测试过,并且两者都表现出类似的行为,类似于以下内容:
Request.Cookies["xxxxxxxxxx"].Name returns: xxxxXxXXXX
All XXXXXXXXXX Cookies:

    xxxxXxXXXX
    xXxxXxXXXx
    XxxxxXxXXx
    XXXxXxXXxX

它显示:
- 在Chrome和Firefox中,Cookies区分大小写。 - .Net Framework可以处理区分大小写的Cookies(这就是为什么它可以循环遍历所有这些Cookies)。 - Request.Cookies [“xxxxxxxxxx”]不区分大小写(这就是为什么它返回与名称不区分大小写匹配的第一个Cookie)。
正如其他答案中提到的那样,新的RFC表明Cookies区分大小写,并且Chrome和Firefox似乎以这种方式处理它。.Net Framework可以处理区分大小写的cookie,但它实际上想要对待cookie不区分大小写,并且它的许多函数确实以这种方式处理cookie(Cookies [],Cookies.Set()等)。这种不一致可能会导致许多难以跟踪的错误。
TestCookie.aspx:
<%@ Page language="c#" AutoEventWireup="false" validateRequest=false %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
    <title id="title">Test Cookie Sensitivity</title>
</head>
<body>
<p>Request.Cookies["xxxxxxxxxx"].Name returns:
<%
    HttpCookie cookie2 = Request.Cookies["xxxxxxxxxx"];
    if (cookie2 == null) Response.Write("No cookie found");
    else Response.Write(cookie2.Name);
%>
</p>
<h3>All XXXXXXXXXX Cookies:</h3>
<ul>
<%
    foreach (string key in Request.Cookies.Keys)
        if (key.ToLower() == "xxxxxxxxxx") Response.Write("<li>" + key + "</li>");
    Random rand = new Random();
    StringBuilder name = new StringBuilder();
    for (int i = 0; i < 10; i++) {
        if (rand.Next(2) == 0) name.Append('x');
        else name.Append('X');
    }
    HttpCookie cookie = new HttpCookie(name.ToString());
    cookie.HttpOnly = true;
    cookie.Expires = DateTime.Now.AddMonths(1);
    Response.Cookies.Add(cookie);
%>
</ul>
</body>
</html>

2
这可能只是与.NET API有关,与HTTP标准无关的问题... - Pacerier
1
当然。除了其他答案中的RFC讨论之外,我只想提供一些确认的结果,以便我们知道浏览器的行为方式,以及.NET的奇怪行为如何使我陷入困境(并可能会影响其他人)。 - jackbean818

3
似乎cookie实际上是区分大小写的。这个问题有些混淆。有趣的是,MSDN说得不一样:
“Cookie名称不区分大小写”
来源:http://msdn.microsoft.com/en-us/library/ms970178.aspx文章底部显示为©2002,可能已过时。
此外,在asp.net论坛上也提出了这个问题:http://forums.asp.net/t/1170326.aspx?Are+cookie+names+case+sensitive+,答案似乎是区分大小写的。
发生了什么?MSDN说不区分大小写,其他技术则说区分大小写。为确保准确性,我使用ASP classic进行了测试。

代码

hashUCASE = Request.Cookies("data")("Hash")
hashLCASE = Request.Cookies("data")("hash")

Response.Write "<p> hashUCASE = " & hashUCASE
Response.Write "<br> hashLCASE = " & hashLCASE


cookieNameUCASE = Request.Cookies("Data")
cookieNameLCASE = Request.Cookies("data")

Response.Write "<p> cookieNameUCASE = " & cookieNameUCASE
Response.Write "<br> cookieNameLCASE = " & cookieNameLCASE

Response.End

结果

hashUCASE: EE3305C0DAADAAAA221BD5ACF6996AAA
hashLCASE: EE3305C0DAADAAAA221BD5ACF6996AAA

cookieNameUCASE: name=1&Hash=EE3305C0DAADAAAA221BD5ACF6996AAA
cookieNameLCASE: name=1&Hash=EE3305C0DAADAAAA221BD5ACF6996AAA

如您在结果中所见,“Hash”值是使用大写字母创建的,即使您使用小写字母进行请求,它返回的仍然是相同的值,这使得它不区分大小写。在此MS技术下,它不区分大小写。
结论:因此,在ASP classic中使用Request.Cookies()时,与Microsoft所说的一样,它是不区分大小写的。但是等等,它又变成了区分大小写?这可能意味着是否区分大小写取决于向浏览器发出请求的服务器端技术,该技术可以规范化cookie名称以进行请求,从而使其不区分大小写。但这是我们必须测试验证的另一件事情。
我的建议是,使用您正在使用的任何技术进行测试,并在代码库中建立标准,与您的团队达成协议。例如,如果要使用cookie,请决定每次在代码中使用时它是否始终以小写或大写形式编写。这样,在您的代码中,它将始终以相同的大小写方式声明,就不会有大小写敏感性问题。
简而言之:只要您遵循cookie名称的约定,就不会出现大小写敏感性问题。

这不是一个ASP问题...由于我们显然无法决定用户将使用哪些浏览器,因此如果Cookie不区分大小写(或反之亦然),我们不能强制规定它们必须区分大小写。 - Pacerier
@Pacerier 确实,这就是我在最后一段中所提出的观点。制定一个始终使用小写字母的约定并始终测试你的东西是一个例子。 - delroh

2
根据RFC 2109 - HTTP状态管理机制,cookie名称(也称属性名称)是不区分大小写的

4.1 语法:通用

两个状态管理头部Set-Cookie和Cookie具有共同的句法属性,涉及属性-值对。以下语法使用符号表示,并使用HTTP / 1.1规范[RFC 2068]中的DIGIT(十进制数字)和token(非特殊、非空格字符序列)来描述它们的语法。

av-pairs        =       av-pair *(";" av-pair)
av-pair         =       attr ["=" value]        ; optional value
attr            =       token
value           =       word
word            =       token | quoted-string

属性(名称)(attr)不区分大小写。标记之间允许有空格。请注意,虽然上述语法描述将值显示为可选项,但大多数属性都需要它们。

这与Ianzz的答案相符吗? - Pacerier
8
RFC 2109已被RFC 6265(通过RFC 2965)所取代;RFC 6265中不包含您引用的定义。 - lanzz
我猜测,在后来的RFC中,将cookie名称与属性名称混淆的做法被有意地删除,原因恰好是为了区分大小写。 - lanzz
根据MSDN的说明,.net仍然遵循RFC 2109标准 - 在解析HTTP响应头时支持以下cookie格式:原始Netscape规范、RFC 2109和RFC 2965 这也可以在.net源代码中看到。 - Woodman

1
根据MSDN,cookie名称不区分大小写。但是,我不确定这是否只是ASPX/IIS特定的实现。我认为这也取决于Web服务器和语言。
如果您发送名为“UserID”的cookie,则浏览器将确保将其作为“UserID”而不是“userid”发送回来。

是的,我也在想这是否只是一个ASPX实现:http://forums.asp.net/t/1170326.aspx/1 - Pacerier

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接