今天同事遇到一个问题,大概描述如下:
浏览器已经接收指令,之前在一级域名下存储了相关的信息。这里为了简化问题,假设我们有两个应用 A 和 B,域名分别为:a.b.com
和c.a.b.com
。(显然 B 是 A 的一个子域)。
上面的描述就是:在.b.com 这个一级域名下,我们已经成功写入了一个 cookie,假设为:b=level1
。
在正常用户的浏览行为中,应用 A 会向自己的域下写入a=level2
(domain:a.b.com
)。
在 A 正常的页面中,有些场景会有异步的请求发出到 B 应用的页面(用于获取数据),合理的一种想法是:发送到 B 应用的请求,应该携带着上面的 b=level1
,a=level2
这两个 cookie 信息到 B 应用的服务器去才对。但是,实际的情况是,b=level1
被如愿携带上来,但是 a=level2
这个信息却被丢弃了!(确切的说是没有跟着 request 一起被发送到 B 的服务端)。
为啥?在访问子域应用时,不是父域名下的 cookie 都应该被携带上来吗?就像上面的 b=level1
那样?
其实,关于这点,在 cookie 的 RFC 规范中,并没有太明显的说明,至少我没有看到,即使又看了一遍 RFC6265 中关于 Domain Matching 的描述也是如此。
但实际的使用过程中,某个域下的 cookie 如果希望能够被他的子域具有可见性(即可以读取),必须要注意的一点是,应该保证这个 cookie 在被 Set 的时候,应该以 ”.” 开头。回到上面的例子,之所以 a=level2
这个 cookie 没有在用户浏览器请求 B 应用时被携带到 B 的 server 端,就是因为 a=level2
这个 cookie 的 domain 不是.a.b.com
,而是a.b.com
。
事实上,上面例子中的 A 应用,在向自己的域名下写入 a=level2
这个 cookie 时,压根就没有显示的设置 domain 这个属性,这样一来,浏览器接受到这个 Set Cookie
的请求时,就会以默认以当前应用的域名作为 cookie 的 domain。(不过据说某些版本的 Firefox 到是会自作聪明的在当前域名的前面自动加上一个点,这个待验证!)
这一个小点的区别,还是很容易被忽略的,不过产生的浏览行为还是有细微差别的。(涉及到 cookie 是否上传,是否占用网络流量等)
PS:关于上面说到的那个问题,stackoverflow 上的这个有个截图,看着说明就直观很多了。