Radic Feng的专栏

唯在分享

Cookie的优先级,你可能误解的

关键字: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
现在向sub1.mydomain.com/us/index.action发送请求,request发送到服务器的cookie里tokenId会是什么呢?

答案

多个值一起带去,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后:

  • Apache会根据URL反向代理(reverse proxy)到Server1或者Server2;
  • Server 1和Server 2都会为请求创建session,就产生名为sessionid的session cookie;
  • Server 2也可能作为服务器端代理,需要能够从request中该浏览器对server 1的session id,从而代替用户从server 1获取一些信息。

我原本的思路是:

将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值修改下,就不会相互干扰了!

阅读更多
个人分类: 互联网
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭