Cookie教程-domain属性

424 阅读6分钟
HTTP Cookies
## domain属性的含义 `domain`属性表示你希望当前Cookie要设置在哪个域名下。

domain属性名和其值不区分大小写,不是必须设置,可选。

名词介绍

在介绍它之前我们先介绍几个名词:

  • 公共域名后缀 comorgnettech都是公共后缀。但是远不止这些,已知的公共后缀在这里:publicsuffix.org/list/public… 这里要注意的是,github.io也是公共的后缀,因为a.github.iob.github.io分别代表完全不同的项目主页。a项目和b项目毫不相干,但是它们都共享github.io域名,因此github.io这种知名站点就成了公共后缀,因此a.github.iob.github.iosamesite规则认为是不同的网站。

  • 子域名和父域名:域名是继承结构的,x.itthink.techitthink.tech的下级域名,itthink.techx.itthink.tech的上级域名。每个域名是其所有下级域名的父域名,每个域名的下级域名都算是其子域名。这里就不写精确的定义了,用复杂的定义来说一个简单的事情,反而不利于理解。相信大家通过例子已经明白什么意思了。

  • 环境域名:对于在浏览器中运行的Javascript来说,它的域名环境就是当前浏览器地址栏中访问的域名。对于一个Http请求来说,它的域名环境是指当前Http请求的URL中的域名。(仅用于本文,并不是公共的名词)

有了上面的知识,咱们再来看domain代表什么意思。

domain值的限制

  • domain的值必须是当前环境域名或其父域名
  • 不可以是公共域名后缀
  • 不可以是环境域名的子域名
  • 不可以是其它域的域名,例如,环境域名为itthink.tech时是绝对不可以设置baidu.com域名的Cookie的,因为它们属于完全不同的域。

domain的限制来看,每个域名或许可以共享其父域名的Cookie,但是绝对不可以共享其子域名和兄弟域名的Cookie。这和继承的概念一致。

domain值的含义

按照最新的标准,domain指定的域名和其所有子域名都可以访问当前要设置的Cookie。 例如:domain=itthink.tech,代表itthink.tech和其所有子域名都可以访问当前Cookie。

但是在之前的标准中,如果希望domain所指域名的子域名也可以获取Cookie的话,需要在域名前面加.。 例如:domain=.itthink.tech代表可以支持itthink.tech和其所有子域名。 新标准对老标准进行了兼容,也就是说虽然新标准不需要前缀.,但是如果你写了前缀也是可以的。

举例总结一下:domain=itthink.tech等同于domain=.itthink.tech,均代表当前Cookie可以在itthink.tech和其环境子域名下被访问。这两种写法均得到了所有主流浏览器的支持。

端口不在Cookie的考虑范围内

在URL中,域名后面有时候会带上端口,一般情况下,域名相同端口不同会指向不同的服务,按理说Cookie是不应该共享的,但是实际情况是,Cookie完全忽略端口的存在,Cookie不具有端口隔离性。这个是Cookie弱点之一。 举例如下: www.itthink.tech:8080www.itthink.tech:3000,这两个域名对于Cookie来说没有区别,它们的Cookie是共享的。

document.cookie并不能获取domain

大家对document.cookie的理解会有一个重大的误区。

因为设置document.cookie时会有各种Cookie的属性,所以大家理所当然的认为通过读取document.cookie也可以获取Cookie的属性。

这是一个很容易犯的错误。事实上读取document.cookie时,只能读取到当前环境下允许的Cookie的名字和值,Cookie的属性是无法读取的,包括domain属性。

document.cookie不是一个普通的属性,设置和读取它,会触发settergetter。向document.cookie赋值和读取document.cookie的值,两个值是不一样的概念。

事实上JavaScript目前还没有办法获取到Cookie的任何属性或者叫元数据,包括domain

即使是服务端,也无法从HTTP请求中获取到Cookie的属性。

举例如下:

document.cookie = `token=token2; domain=itthink.tech`;
// 将变成:token=token2
console.log(document.cookie);

可以看到读取document.cookie只能读取到当前环境允许的Cookie的名字和值。

不设置domain的情况

domain如果不设置,也具有特殊的意义。此时的Cookie是Host-Only的,也就是说只有当前环境域名可以访问。假设我们的环境域名是itthink.tech,那domain的默认值就是itthink.tech,这里要注意的是,它和domain=itthink.tech并不是一回事,domain=itthink.tech代表itthink.tech和其子域名,而如果不设置domain则代表仅仅是itthink.tech。 不过之前的Edge版本和IE11之前的版本是例外,如果不设置domain,当前Cookie将适用于当前环境域名和所有其子域名。

去除点前缀带来的小混乱

新标准去除了前缀.给Cookiedomain的设置带来了一点歧义。 举例说明如下: 假设我们在itthink.tech网站的调试控制台中运行:document.cookie = 'x=y; domain=itthink.tech',调试工具的控制面板一般会显示成以下这样: image 可以看到domain那一项变成了.itthink.tech。浏览器为什么还要使用被废弃的老标准来显示domain字段呢? 假设我们暂且显示成itthink.tech,这时我们再设置一个不带domain的新Cookie,这时的domain栏应该显示为空,但是空的话用户在查看该面板时就无法知道这个Cookie属于哪个域名,所以需要显示其默认值itthink.tech,也就是说没有设置domain时,domain栏显示了itthink.tech,而且这个Cookie是Host-Only的,仅当前域名可以使用该Cookie,而当显式的设置domainitthink.tech时,这个Cookie并不是Host-Only的,但是其值如果也显示成itthink.tech,则无法通过domain栏位来区分是否是Host-Only的,所以浏览器通过加.的方式来区分,有.前缀的表示指定域名和其子域名均可共享该Cookie,没有的表示当前Cookie没有设置domain,是Host-Only的。

Cookie是按域隔离的

domain就像是Cookie的命名空间一样,即使Cookie的名称相同,只要domain不同,它们就不会被合并读出,它们会被分别读出来。 例如x.itthink.tech网站,分别设置Cookie如下:

document.cookie = `token=token1;`;
document.cookie = `token=token2; domain=itthink.tech`;
document.cookie = `token=token3; domain=x.itthink.tech`;
console.log(document.cookie);
// 输出 token=token1; token=token2; token=token3
// 各个浏览器的输出顺序不一定一致

它们都有相同的Cookie名称,但是domain不同,这时document.cookie会输出三个token,各个浏览器的输出顺序不一定一致。Http也是一样的情况。

这种情况想必是我们要尽量避免的,大家一定要小心。

修改Cookie的注意点

修改Cookie时一定要注意,修改时的domain必须和之前设置的domain相同。 例如Cookietoken=afdsaf; domain=itthink.tech,我们通过重新设置来修改它:token=gggd; domain=www.itthink.tech;这里使用了不同的domain,实际执行时将无法修改之前的token,而是新添加了一个叫token的Cookie,它的domainwww.itthink.tech

总结

domain属性是Cookie中一等重要的属性,大家在设置Cookie时一定不要忘记设置domain,否则容易带来意想不到的Bug。

此篇结束。