Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

浏览器缓存 之 cookie #22

Open
HXWfromDJTU opened this issue Sep 23, 2020 · 0 comments
Open

浏览器缓存 之 cookie #22

HXWfromDJTU opened this issue Sep 23, 2020 · 0 comments

Comments

@HXWfromDJTU
Copy link
Owner

HXWfromDJTU commented Sep 23, 2020

前言

相比较于其他浏览器本地存储,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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant