赞
踩
在Web前端开发时,我们经常会遇到一些浏览器存储相关的工具,例如Cookie。Cookie的英文本意是曲奇,但是在Web中,它被用作浏览器中存储的数据。Cookie都是name=value
的结构,name和value都为字符串。
Set-Cookie
。Set-Cookie
后,会将Cookie保存下来下图分别为设置Cookie和携带Cookie的示例。
设置Cookie
携带Cookie
在上面Set-Cookie
的图中,我们可以看到,设置Cookie时,除了最前面的name和value之外,还配置了其他属性。实际上Cookie还有更多属性,可以查看浏览器的Application-Storage,获取当前网站的Cookie。
这里简单描述一下每个属性的含义:
属性 | 含义 |
---|---|
Name | Cookie的名称 |
Value | 对应名称的值 |
Domain | Cookie的域名 |
Path | Cookie生效的路径 |
Expires | 过期时间,过了这个时间后Cookie失效 |
Max-age | 生效时间,表示Cookie在多长时间后失效 |
Size | Cookie的长度,为name和value的长度和 |
HttpOnly | 防止通过JavaScript访问Cookie |
Secure | 只在HTTPS协议的情况下才会将Cookie传到后端 |
SameSite | 是否允许跨站请求时发送Cookie |
Partitioned | 第三方Cookie分区 |
Priority | 优先级 |
下面我们对其中一些属性和作用进行讨论。
Cookie是有生命周期的,在设置Cookie值时,可以同时设置有效期。当超过了这个有效期之后,Cookie便会失效,前端请求时,不会携带过期的Cookie。
Cookie的有效期有三种类型:
这里的Session并不是存储在服务端的Session,而是指浏览器会话。如果Cookie的有效期为Session,一般关闭会话时,Cookie便会失效;而一些浏览器重启时,也会将会话恢复,此时Cookie并不会失效。
Expires表示过期时间,是一个确定的日期时间。例如Expires=Wed, 21 Oct 2015 07:28:00 GMT
。当浏览器端本地的当前时间超过这个时间时,Cookie便会失效。
Max-age表示Cookie的存活时间,以秒作为单位。例如Max-age=3000
。当获取到该Cookie后开始倒计时,3000秒之后便失效。
注意:上述的生命周期都是服务端指定的。如果设置了Expires,则是把服务器时间和浏览器本地时间相比较,如果时间不同步,配置就会出现问题。而Max-age设置的是秒数,始终是浏览器本地时间自己相比较,不会出现时间不同步的问题。
作用范围主要由Domain和Path两个属性来控制。
Domain用来设置Cookie作用的域名,即Cookie在哪个网站生效。默认情况下,生效的域名为当前访问的域名。例如我们在jzplp.com
设置的Cookie,就只能限制该网站内使用。
如果访问的网站有多级域名,则Cookie默认仅在访问的多级域名内生效。如果希望在更大范围内生效,可以指定域名。
例如我们在a.jzplp.com
下设置的Cookie,就只在这个域名下生效。但是如果我们在设置cookie时同时设置了domain=jzplp.com
,则该Cookie可以在jzplp.com
下的任何域名内生效。比如:
jzplp.com
a.jzplp.com
b.jzplp.com
c.d.jzplp.com
有时候,我们希望Cookie仅仅在部分路径下生效,就可以使用Path进行限制。这里的路径就是网站的路由。默认的path=/
,即在所有路径下生效。
如果设置了path=/abc
,则只在/abc
路径下生效。比如:
jzplp.com
不生效jzplp.com/abc
生效jzplp.com/abc/def
生效jzplp.com/qaz
不生效jzplp.com/qaz/abc
不生效不同的浏览器允许的Cookie大小并不相同,通常的限制为:
网络上也有人整理各种浏览器详细的限制。
IE6.0 | IE7.0/8.0 | Opera | Firefox | Safari | Chrome | |
---|---|---|---|---|---|---|
cookie个数 | 每个域为20个 | 每个域为50个 | 每个域为30个 | 每个域为50个 | 没有个数限制 | 每个域为53个 |
cookie大小 | 4095个字节 | 4095个字节 | 4096个字节 | 4097个字节 | 4097个字节 | 4097个字节 |
一个Cookie的大小可以在浏览器中查看Size属性得知,这个大小是key和value的和。
当Cookie的数量超过限制时,路蓝旗会清除一部分Cookie。清除哪些合适呢?Priority属性用来定义Cookie的优先级,低优先级的Cookie会优先被清除。
Priority属性有三种: Low, Medium, High
通常的Cookie在客户端(一般指浏览器)是可以通过脚本代码(一般指js)访问的。方式可见JavaScript中操作Cookie。
如果设置了HttpOnly属性,则该Cookie在浏览器中无法通过js代码访问,经过我测试也无法写入。这样可以防止窃取Cookie信息,一般用来防止XSS攻击。
Samesite是Cookie的跨站属性,也可以看做是“更高级”的作用范围设置。部分内容参考了几篇文章:SameSite Cookie,防止CSRF攻击, Cookie 的 SameSite 属性
一般浏览器限制请求的内容是按照跨域来判断的,比如XHR和fetch。但是Samesite限制的并不是跨域,而是跨站。跨站是比跨域更宽松的一种限制。可以这么说如果跨站,那么肯定会跨域,但如果跨域,那么不一定会跨站。
a.jzplp.com
与b.jzplp.com
jzplp.com:8000
与jzplp.com:9000
在上面子域名的的跨站说明中,是存在漏洞的。我们假设这样的情况:
a.jzplp.com
与b.jzplp.com
实际属于同站jzplp.com.cn
与other.com.cn
实际属于跨站jzplp.github.io
与other.github.io
实际属于跨站可以看到,上面的三个域名格式是相同的,都使用了两个点来分隔。
第一个属于同站。看第二个例子,com.cn
是我们国家颁布的二级域名并不是指的某一个网站。显然这种域名后缀,并不能认为是同站。除了我国,还有其他国家和组织也会公布这种二级甚至更高级的域名。再看第三个例子,是Github提供的网站域名。使用github.io
后缀的网站,显然也不能认为是同站。
因此,仅仅通过网址格式匹配,是无法判断是否同站的。因此,浏览器会维护一个列表:Public Suffix List。列表里面记录了这些需要特殊匹配的域名后缀,比如上面提到的com.cn
与github.io
等等,这个叫做有效顶级域名,eTLD。在遇到一个域名时,会首先匹配列表中的后缀,再把eTLD+1个字段相同表示为同站,不同表示为非同站。
例如 列表中的域名后缀为com.cn
,那么eTLD+1个字段表示为jzplp.com.cn
。那么a.jzplp.com.cn
与b.jzplp.com.cn
属于同站, jzplp.com.cn
与other.com.cn
属于跨站。
Public Suffix List列表的内容,这个列表会随着浏览器的更新而更新。
Public Suffix List除了应用在Samesite中,还在其他地方有应用。例如Cookie中的Domain也使用了这里eTLD+1个字段作为设置的最大范围。
当我们在浏览器中访问一个网站,在输入一个网址后,首先返回的是一个HTML页面。而在这个页面中还可以继续包含其他请求,比如图片,iframe,fetch等等。这些请求可以被分为两类:
window.open()
,<a>
链接,form表单提交等。<script>
,<css>
,<img>
等标签,fetch,XHR请求等。可以看到,这两类的主要区别是:第一类请求直接把页面替换了,或者打开了一个新的页面,即——和原有的页面不属于同一个页面。而第二类请求依然在原页面上,仅仅是做一些内容上的更新。这个请求分类与Samesite配置相关。
上面跨站,eTLD和请求分类,是理解Samesite设置的基础。Samesite设置有三种:
上面我们介绍过的SameSite属性,是为限制第三方Cookie进行跨站传输而设置的。但是在很多场景下,SameSite属性并不够用,我们需要“更更高级”的作用范围设置。这就是Partitioned属性————Cookie分区设置,也叫作CHIPS。关于提案和讨论可以查看GitHub-CHIPS
SameSite属性仅仅能控制网站是否发送第三方Cookie,但是不能针对不同的网站来源做出不同的Cookie反应。例如一个网站对于外部的网站需要记录不同的第三方Cookie。Partitioned属性允许在请求第三方cookie,即跨站传输Cookie后,浏览器设置一个分区Key(PartitionKey),标明当前访问的网站来源。后续浏览器再次请求第三方Cookie时,浏览器会判当前网站的域名与分区Key是否一致。如果一致才发送这个Cookie,如果不一致则不发送。
假设C网站开启了分区Cookie设置,例如Set-Cookie: value=1; Partitioned;
。有A网站和B网站分别都会调用C网站的接口。
这样,就实现了对第三方Cookie更细粒度的访问控制。
除了独立分区之外,浏览器还在讨论其他关于第三方Cookie作用范围设置的方法,例如SameParty属性等等。可以看下:详解Cookie新增的SameParty属性
在浏览器中使用js,可以直接设置Cookie。一次只能设置一个Cookie。但是可以同时对单个Cookie的属性进行设置,每个属性使用分隔符;。
document.cookie = "a=1;";
document.cookie = "a=1; doamin=jzplp.com";
document.cookie = "a=1; doamin=jzplp.com;path=/abc";
修改某个Cookie,相当于对其进行重新设置。
document.cookie
读取到的是一个字符串,内容为该页面的所有Cookie,不同的Cookie用分隔符;分隔。只能读到key和value,其余的属性读不到。例如:
"a=1; b=2"
js中没有直接删除Cookie的方法。如果需要删除某个Cookie,需要重新设置该Cookie,将它的有效期直接设置为过期,即可实现删除功能。例如:
document.cookie = "a=1; max-age=-1";
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。