我是一名开始涉足Java的.NET开发人员.
在.NET中,我可以将cookie的值设置为带有空格的字符串:
new HttpCookie("myCookieName", "my value")
- 当我在客户端(JavaScript)读取该值时,我得到我期望的值(我的值).
如果我在Java servlet中做同样的事情 - new Cookie("myCookieName", "my value")
我得到的值包括双引号("我的值").
为什么不同?我错过了什么吗?人们如何在Java世界中处理这个问题?您是否对值进行编码,然后在客户端进行解码?
当您使用下面提到的值之一设置cookie值时Cookie#setValue()
,
对于版本0 cookie,值不应包含空格,括号,括号,等号,逗号,双引号,斜杠,问号,符号,冒号和分号.在所有浏览器上,空值的行为可能不同.
那么普通容器将隐式地将cookie设置为版本1(RFC 2109规范)而不是默认版本0(Netscape规范).Servlet API没有指定行为,容器可以自由地实现它(例如它可以抛出一些IllegalArgumentException
).据我所知,Tomcat,JBoss AS和Glassfish在隐式更改cookie版本方面表现完全相同.对于至少Tomcat和JBoss AS,这是针对此安全问题的修复的结果.
版本1 cookie看起来像这样:
name="value with spaces";Max-Age=3600;Path=/;Version=1
而版本0兼容的cookie看起来像这样:
name=value%20with%20spaces;Expires=Mon, 29-Aug-2011 14:30:00 GMT;Path=/
(请注意,URL编码的值对版本0有效)
重要说明是Microsoft Internet Explorer不支持版本1 cookie.即便不是当前的IE 11发布.它会将引号解释为整个cookie值的一部分,并将相应地处理和返回.它不支持该Max-Age
属性,它将完全忽略它,导致cookie的生命周期默认为浏览器会话.您显然正在使用IE来测试您的webapp的cookie处理.
为了支持MSIE,如果它包含可能对版本0无效的字符,则您需要自己对cookie值进行URL编码和URL解码.
Cookie cookie = new Cookie(name, URLEncoder.encode(value, "UTF-8")); // ...
和
String value = URLDecoder.decode(cookie.getValue(), "UTF-8")); // ...
为了支持全球受众的第1版cookie,你真的会等待微软修复缺乏MSIE支持的问题,并且修复后的浏览器已经成为主流.换句话说,它需要很长时间(更新:截至目前,5年以后,它似乎永远不会发生).同时你最好坚持使用兼容0的cookie.
据我所知,空格必须用cookie编码.不同的浏览器对未编码的cookie的反应不同.您应该在设置cookie之前对其进行URL编码.
String cookieval = "my value"; String cookieenc = URLEncoder.encode(cookieval, "UTF-8"); res.addCookie(new Cookie("myCookieName", cookieenc));
ASP.NET自动进行编码,在Java中你必须自己完成.我怀疑您看到的引号是由用户代理添加的.