案例:
在項目中通過Cookie方式臨時存放檢索條件,不小心在Cookie值中使用了特殊符號"@",導致在服務器端無法正確解析Cookie值。
之所以說"不小心",根本原因是對於Cookie的理解不夠深入。
實際上在開發環境使用run-jetty-run插件進行調試時並未發現問題,經驗證:
在jetty下可以在Cookie中使用特殊符號@,但是在Tomcat下不能在Cookie中使用特殊符號@。
Cookie規范經歷了多個版本發展,分別是: RFC 2109(1997年),RFC 2965(2000年), RFC 6265(2011年)。
Cookie值的約定見rfc2068描述(https://tools.ietf.org/html/rfc2068):
Many HTTP/1.1 header field values consist of words separated by LWS or special characters. These special characters MUST be in a quoted string to be used within a parameter value. token = 1*<any CHAR except CTLs or tspecials> tspecials = "(" | ")" | "<" | ">" | "@" | "," | ";" | ":" | "\" | <"> | "/" | "[" | "]" | "?" | "=" | "{" | "}" | SP | HT
對應的,在Tomcat實現中javax.servlet.http.Cookie對特殊字符的定義如下:
class RFC6265Validator extends CookieNameValidator { private static final String RFC2616_SEPARATORS = "()<>@,;:\\\"/[]?={} \t"; RFC6265Validator() { super(RFC2616_SEPARATORS); } }
顯然,相應特殊字符在Tomcat下不要在Cookie中使用,否則會導致Tomcat無法正確解析Cookie信息。
而跟蹤jetty源碼發現,org.eclipse.jetty.server.CookieCutter方法parseFields()並不會把Cookie中的"@"作為特殊字符過濾掉。
總結:
雖然在jetty中僥幸可以使用特殊字符@作為Cookie值,但是建議在Cookie中不要使用任何特殊字符,否則應用程序的移植性太差。
而且,對於存儲的Cookie,最好進行編碼處理。如通過escape()方法對Cookie進行編碼:
function setCookie(c_name,value,expiredays) { var exdate = new Date(); exdate.setDate(exdate.getDate() + expiredays); document.cookie=c_name + "=" + escape(value)+ ((expiredays == null) ? "" : ";expires=" + exdate.toGMTString()); }
【參考】
https://en.wikipedia.org/wiki/HTTP_cookie
https://tools.ietf.org/html/rfc2109
https://tools.ietf.org/html/rfc2965
https://tools.ietf.org/html/rfc6265
http://www.blogjava.net/stone2083/archive/2010/11/03/336923.html 關於cookie特殊字符的一點理解
https://www.biaodianfu.com/cookie-symbol.html Cookie與特殊字符