blog icon indicating copy to clipboard operation
blog copied to clipboard

浏览器缓存 之 cookie

Open HXWfromDJTU opened this issue 4 years ago • 0 comments

前言

相比较于其他浏览器本地存储,cookie的特点在于符合匹配规则,则自动携带。服务端与客户端双方都可以写入。Cookie 的存在使得基于无状态的HTTP协议下,储存信息成为了可能。

cookie

首先定义一下,cookie是一段记录用户信息的字符串,一般保存在客户端的内存或者硬盘中。

服务端对cookie进行写入

cookie的创建是由服务端的响应头,其中带着set-cookie的字段,来对客户端进行cookie设置。

基础属性

属性名 作用
Name 表示cookie的名称
Value 字段表示cookie的值
size 表示cookie的大小

作用域限制

属性名 作用
domain 表示cookie有效的域,默认值为当前域名
path 字段表示cookie有效的路径,默认值为/表示全匹配。
读取向上匹配

若不显示设置cookiedomain值,则浏览器会处理为生成一个只对当前域名有效的cookie。比如在map.baidu.com下,我们生成了一个cookie,但没有指定domain值,那么这个cookie,只有在访问map.baidu.com时候有效,而abc.map.baidu.comuser.map.baidu.com都是拿不到的。

Path 匹配
  • domainwww.abc.com,path/sale/img,则只有匹配www.abc.com/sale/img路径的资源才可以读取cookie
  • path 的规则是模式匹配,也就是向后匹配,上面的例子也能匹配www.abc.com/sale/img/qqq/ss

安全与时效

属性名 作用
Expire / Max-Age 表示为cookie的有效时间,默认值session,也就是指浏览器session,也就是用户关闭浏览器就会清除掉这个cookie。
Secure 表示该cookie在安全的协议下才会生效
HttpOnly 只用于http请求,本地脚本不能够读写
SameSite 标明该cookie是否在跨站点请求时发送

有效时间

  • Expire 的值为一个日期时间,则表示在此时间前,cookie始终有效。
  • Max-Age 的值为一个秒值

协议安全

  • 若设置为true,则表表示此cookie只会在https协议或者ssl等安全协议下进行发送。
  • 网页中通过 js 去设置Secure类型的 cookie,必须保证网页是https协议的。在http协议的网页中是无法设置secure类型cookie的。
    document.cookie = "username=cfangxu; secure"
    

HttpOnly

  • 表示该cookie只会在http请求传输的时候携带
  • 不能够被本地的JavaScript脚本所读取到。(可以简要的防止XSS攻击)。

SameSite

SameSite 用于限制第三方cookie的使用, 在 a.com 下发起对 b.com 的请求,cookie携带与否,将取决于SameSite这个属性。

SameSite 取值
  • Strict 表示绝对禁止所有的跨站cookie
  • None 则表示不启用该规则
  • 默认为Lax, 限制强度介于 StrictNone 之间, 相对于Strict仅允许以下三种情况的cookie携带
    • <a href="..."></a> 连接跳转
    • <link rel="prerender" href="..."/> 预加载
    • <form method="GET" action="..."> GET形式的表单
same site 与 same origin
  • 大多数人应该知道 同源策略 中的 same origin,但 same site中的 site,指的则是有eTLD + 1,其中 eTLD 指的是 effective top-level domain(有效顶级域名)
  • 大多数有效顶级域名和我们认知的顶级域名一致。
  • 少数有效顶级域名,与熟知的顶级域名不一致。比如一些二级域名github.com .gov.uk .org.uk也是有效顶级域名。参考👉这份名单
第三方cookie隐私问题
  • 你在闲逛某个网站A的时候,使用管理工具查看cookie,发现除了本域下的cookie,还经常存在某些知名搜索网站的cookie

  • 这并不是什么秘密了,而是搜索网站跟踪手机用户习惯的主要手段

  • 比如你的网站加入了某某广告联盟,则在你的网站中加入上报脚本,告知广告联盟这个用户来过这里,帮助联盟构建更完整的用户画像。

SameSite 小结
  • 因为欧美国家对用户隐私的关注,来到2020年秋天的这个时间,已经被大多数主流浏览器所支持。
  • 对网站开发中,使用CORS调用部署在其他站点的第三方API存在影响

CORS 请求中的 cookie

关于域的设置,👆前面讲解domain部分有介绍。

cookie中的domin设置的跨域是指跨子域名都不可以访问,例如www.baidu.commap.baidu.com是不可以跨域进行读取内容的。(看上述domain第一条规则)

CORS下的cookie跨域
  • 首先服务端要返回Access-Control-Allow-Credentials表明允许跨域请求携带cookie,并且Allow-Control-Allow-Origin字段也不能模糊的表示为*,而要写明cookie发送的域

  • 再者,客户端也要设置请求的携带cookie

// 原生ajax请求设置跨域携带cookie
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

客户端读写Cookie

读取 cookie

读取cookie可以使用docuemnt.cookie

document.cookie = 'userId=xusfh123; maxAge=5000;path=/;secure'
如何写入
  • 写入cookie也是用的是这个属性,但要注意,但是不支持同时设置多个cookie,需要分开多次调用设置属性值。

  • 删除一个cookie的方法就是把对应字段的cookie值置空。

实现单点登录 cookie ✅

当服务器想共享cookie值给所有二级域名的时候,我们的cookie就应该设置为共同的上一级域名。比如.baidu.com(常用于单点登录)。建议设置cookie时候,都带上.通配符号,如.a.b.c.baidu.com

允许向上写入 ✅

一个服务器能够设置domian的有效的范围是,从自身域名开始,向上追溯到一级域名。比如a.b.c.baidu.com能够设置有效的cookie-domain是.a.b.c.baidu.com.b.c.baidu.com.c.baidu.com.baidu.com

不允许跨子域写入 ❌

不能够跨上级域名设置其他域的子域。不能够设置.a.u.c.baidu.com。例如如下:

  1. 前端服务部署在 dashboard.swain.com, 服务端api部署在 api.swain.com上
  2. 前端请求后端,后端返回头中,携带的set-cookie中,domain字段为 .dashboard.swain.com
  3. 浏览器控制台得到一个"this. set-cookie domain attribute was invalid with regards to the current host URL".的错误

这就是一个跨子域设置cookie的实例,正确的方式应该设置domain.swain.com

同域同名覆盖 ⚠️

在不domain下的cookie即使同名也不会覆盖,若在同一个domain下,同名的cookie后者会覆盖前者。

低安全级别无法覆盖高安全级别

securehttp-only都象征着更高的对应cookie条目的更高安全级别,当前cookie已经添加了对应安全策略的时候,更低安全策略的cookie写入相对于是无法无盖已存在的旧cookie值。

大小数目有限制

因为cookie会跟随请求自动发送的特性,所以浏览器对对一个域的cookie总大小和数目都有着不同的限制。

浏览器 数目(个/域) 每域下的cookie总大小限制 其他
Firefox 50个 4k
Chrome 53个 4k
Safari 无限制 4k
IE 7+ 50个 <4k 超长则截断,超过数目则使用LRU淘汰
IE 6 20个 <4k 超长则截断,超过数目则使用LRU淘汰
Opera 30个 4k

总结

  1. 不建议cookie当做我们的本地数据仓库使用,而仅仅去存储一些用户的id,sessionID之类的身份验证性的简单数据。
  2. 设置 cookie 需要注意对应的有效范围有效期安全生效条件等属性
  3. 特别注意最近各个浏览器对于SameSite的支持情况,有可能对于你的应用导致致命的bug。

接下来会结合安全隐私方向,说说最常见的用cookie作为用户身份标识,遇到的问题和解决方案。

参考文章

[1] 从url中解析出域名、子域名和有效顶级域名 - alsotang
[2] 干掉状态:从 session 到 token [3] 正确使用cookie中的domain

HXWfromDJTU avatar Sep 23 '20 00:09 HXWfromDJTU