关键字:Cookie,优先级(Precedence, Priority)
问题
Server端分别在不同的域(domain)或者不同的路径(Path)添加了名字相同的Cookie,比如:
Cookie名 | 域名 | Path | 值 |
tokenId | mydomain.com | / | root domain token |
tokenId | sub1.mydomain.com | / | sub1 domain token |
tokenId | sub2.mydomain.com | / | sub2 domain token |
tokenId | sub1.mydomain.com | /us/index.action | sub1 domain /us/index.do token |
答案
多个值一起带去,tokenId=root domain token;tokenId=sub1.mydomain.com;tokenId=sub2 domain token;tokenId=sub1 domain /us/index.do token;
吃惊吧!我本以为同名Cookie会根据domain和path有优先级的。做了个相同domain不同path下同名Cookie的实验,发现在Header里面同名Cookie的两个值都带去了,也有人做root域和sub域的实验,也是这种情况(详述)。我没有查到RFC或者其它官方文档里给出的详述,但有资料说所有值都会带去,并且顺序是不固定的。
参考RFC6265 HTTP State Management Mechanism,可以发现:
4.2.2
In particular,if the Cookie header contains two cookies with the same name (e.g., that were set with different Path or Domain attributes), servers SHOULD NOT rely upon the order in which these cookies appear in the header.
5.3. Storage Model
2. The user agent SHOULD sort the cookie-list in the following
order:
* Cookies with longer paths are listed before cookies with
shorter paths.
* Among cookies that have equal-length path fields, cookies with
earlier creation-times are listed before cookies with later
creation-times.
NOTE: Not all user agents sort the cookie-list in this order, but
this order reflects common practice when this document was
written, and, historically, there have been servers that
(erroneously) depended on this order.
大概就是:RFC推荐在request header中浏览器能够按path的长短排序,越长说明匹配的越精确,顺序越靠前。同时也说明并不是所有的浏览器都遵守这个,并且服务器也不应该依赖于cookie出现的顺序。
源自于对一个解决方案的思考
我对Cookie的兴趣来自sessionid cookie,因为它用来维持request和服务器端session的匹配。有一个场景,如下图所示:
Web应用由Apache后面的两个子应用支撑。浏览器发送请求给Apache后:
我原本的思路是:
将Server 1的sessionid cookie的path设置成根路径(/);将server 2的sessionid cookie的path设置成相对具体的路径,比如/server2/。假设同名cookie有优先级,那么路径具体的cookie的值就会优先带回,那么我就可以同时保持对Server 1和Server 2两个子应用的session了。在Server 2的session没建立时,我也可以在Server 2通过request header拿到Server 1的session。
不随我愿啊!
看来现在可行的方式只有:
Server 1的子应用是成熟的产品,不能修改,只能把Server 2做成sessionless的了,以Server 1的sessionid做主键,在Server 2把用户信息保存到内存数据库中,以此来维护上下文信息。
一个担心:
如果Server 2子应用的开发者一不小心创建了session呢,这时候它产生的sessionid cookie可能干扰Server 1对session id和session的映射啊!!并且恰恰两个server都是在一个domain下。有什么方法可以强迫Server 2永远无法创建session呢?思考中,请大侠教我。。。
多谢Apache Tomcat。我们的应用部署在Apache Tomcat中,Tomcat 5.5之后的版本可以修改默认的sessionid cookie的key值,方式很简单,在bin/catalina.bat中添加如下参数:
JAVA_OPTS="$JAVA_OPTS -Dorg.apache.catalina.SESSION_COOKIE_NAME=MYJSESSIONID -Dorg.apache.catalina.SESSION_PARAMETER_NAME=myjsessionid"
把两个session id的key值修改下,就不会相互干扰了!