为什么带有空格的cookie值到达客户端时会带有引号?

问题描述 投票:0回答:4

我是一名 .NET 开发人员,开始涉足 Java。

在.NET中,我可以将cookie的值设置为其中包含空格的字符串:

new HttpCookie("myCookieName", "my value")
- 当我在客户端(JavaScript)读取该值时,我得到了我期望的值(我的值)。

如果我在 Java servlet 中执行相同的操作 -

new Cookie("myCookieName", "my value")
,我会得到包含双引号的值(“我的值”)。

为什么有区别?我错过了什么吗?在 Java 世界中人们如何处理这个问题?您是否对值进行编码,然后在客户端进行解码?

servlets cookies encoding
4个回答
46
投票

当您使用以下值之一设置 cookie 值时,如

Cookie#setValue()
中所述,

对于版本 0 cookie,值不应包含空格、方括号、圆括号、等号、逗号、双引号、斜杠、问号、at 符号、冒号和分号。空值在所有浏览器上的行为可能有所不同。

然后,普通容器将隐式将 cookie 设置为版本 1(RFC 2109 规范),而不是默认版本 0(Netscape 规范)。该行为不是由 Servlet API 指定的,容器可以自由地实现它(例如,它可能会抛出一些

IllegalArgumentException
)。据我所知,Tomcat、JBoss AS 和 Glassfish 在隐式更改 cookie 版本方面的行为完全相同。至少对于 Tomcat 和 JBoss AS 来说,这是修复此安全问题的结果。

版本 1 cookie 如下所示:

name="带空格的值";Max-Age=3600;Path=/;Version=1

而版本 0 兼容的 cookie 看起来像这样:

名称=值%20with%20spaces;过期=2011年8月29日星期一14:30:00 GMT;路径=/

(请注意,URL 编码值对于版本 0 有效)

重要提示是 Microsoft Internet Explorer 不支持版本 1 cookie。即使不是当前的 IE 11 版本。它将把引号解释为整个 cookie 值的一部分,并相应地处理和返回它。它不支持

Max-Age
属性,并且会完全忽略它,这会导致 cookie 的生命周期默认为浏览器会话。您显然正在使用 IE 来测试您的 web 应用程序的 cookie 处理。

为了也支持 MSIE,如果 cookie 值可能包含对版本 0 无效的字符,您确实需要自己对 cookie 值进行 URL 编码和 URL 解码。

Cookie cookie = new Cookie(name, URLEncoder.encode(value, "UTF-8"));
// ...

String value = URLDecoder.decode(cookie.getValue(), "UTF-8"));
// ...

为了向全球受众支持版本 1 cookie,您真的需要等待 Microsoft 修复 MSIE 支持的缺失,并且修复后的浏览器已成为主流。换句话说,这需要ages(更新:截至目前,5年多后,这似乎永远不会发生)。与此同时,您最好坚持使用版本 0 兼容的 cookie。


5
投票

据我所知,cookie 中必须对空格进行编码。不同的浏览器对未编码的 cookie 的反应不同。在设置 cookie 之前,您应该对其进行 URL 编码。

String cookieval = "my value";
String cookieenc = URLEncoder.encode(cookieval, "UTF-8");
res.addCookie(new Cookie("myCookieName", cookieenc));

ASP.NET 自动进行编码,在 Java 中你必须自己进行编码。我怀疑您看到的引号是由用户代理添加的。


3
投票

这可能与Java对cookie的编码方式有关。我建议您尝试在新 cookie 上调用 setVersion(1) 看看这是否适合您。


1
投票

尝试使用 setVersion(0)。

HttpCookie cookie = new HttpCookie("name", "multi word value");
System.out.println(cookie.toString());

打印:

name=“几个字的值”

但是设置之后

cookie.setVersion(0);
System.out.println(cookie.toString());

打印:

名称=几个字值

编码也是一个好主意,但值周围的引号看起来是一个独立的问题。

© www.soinside.com 2019 - 2024. All rights reserved.