浏览器Cookie机制完全解析
浏览器Cookie机制完全解析
Cookie是Web开发中一个重要的概念,它被广泛应用于用户身份识别、会话管理等场景。本文将从多个维度深入解析Cookie的工作原理、关键属性以及跨域、第三方Cookie等相关话题,帮助开发者全面理解这一机制。
Cookie的背景
HTTP协议是无状态的,这意味着服务端无法区分一个用户第二次请求和一个新用户第一次请求。为了解决这个问题,Cookie被设计出来,用于让服务端记住客户端的信息。
Cookie是一种存储方式
Cookie主要用于存储用户身份信息。它由服务端设置在浏览器上,由浏览器管理,并随着HTTP请求自动发送。在服务端配置允许的前提下,还可以使用JavaScript访问和操作Cookie。
既然Cookie是一种存储方式,用来存储用户身份信息,我们同样可以使用其他的存储方式替代Cookie,但这需要我们自己发送和维护,而Cookie是浏览器自动发送和清理的。
存储容量
Cookie是存储在用户Web浏览器中的小块数据,一般单个Cookie的大小不超过4KB。浏览器在存储Cookie时是以二级域名作为key存储的。通过Chrome设置可以看到当前域名下的Cookie总量。每个二级域名下数量也是有限制的,例如.kuaishou.com | .juejin.cn。通过源码,这里可以看到Chrome设置的最大条数是180。如果一个域名下存储的数量大于当前的最大条数,浏览器将自动清除一些Cookie。清理规则如下:注意不要让Cookie的数量超过限制,尤其要注意设置path属性,否则可能每个path下都有一条相同的Cookie。
Cookie的关键属性
name&value
属性名和属性值,用于存储Cookie的内容信息。
domain
设置了Cookie的作用范围。指定了Cookie发送的主机名,只能设置范围小于等于自己的域名范围。假如没有指定,那么默认值为当前文档访问地址中的主机部分(但是不包含子域名)。
这里关于提到的“小于等于自己的域名”做一个解释:
假如当前domain=sub.test.com
可以设置domain为a.sub.test.com:Cookie只在a.sub.test.com下有效。
可以设置domain为.test.com:Cookie在test.com及其所有子域下有效。
不能设置domain为.other.com:超出sub.test.com的域名范围,浏览器会忽略该设置。
path
指定一个URL路径,只有当路径匹配时,才会向服务器发送Cookie。例如设置“/”这此域下所有路径都可以携带Cookie。如果没有设置默认为当前路径。这可能导致同一个Cookie在不同的路径下同时存在多条记录。所以建议设置。
Expires & Max-Age
设置Cookie有效期。Expires和Max-Age都存在时,Max-Age优先级更高。
- Expires:设置Cookie的过期时间。如果不设置,Cookie会在浏览器关闭时自动失效,称为会话Cookie(Session Cookie)。Expires使用的是具体的日期和时间(例如:Sat, 31 Dec 2022 23:59:59 GMT)。
- Max-Age:设置Cookie在多少秒后过期。与Expires相比,Max-Age是相对于当前时间的持续时间,更加灵活。max-Age > 0, 浏览器会将其持久化,即写到对应的Cookie文件中。当max-Age < 0,则表示该Cookie只是一个会话性Cookie。当max-Age = 0时,则会立即删除这个Cookie。
Secure
标记该属性的Cookie只应通过被HTTPS协议加密过的请求发送给服务端。这有助于保护数据在互联网上传输过程中不被窃取。
HttpOnly
此属性用来帮助防止跨站脚本攻击(XSS),因为标记为HttpOnly的Cookie无法通过JavaScript的Document.cookie API访问。这意味着即使系统有XSS漏洞,Cookie也不会被盗取。
Size与Priority
Cookie的大小一般为4KB,当超出这个范围时会移除旧的Cookie。移除时按照优先级由低到高删除。
SameSite
SameSite属性可以让Cookie在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。
- Strict:Cookie不会随着来自第三方的请求被发送
- Lax:在一些第三方请求场景中发送,例如通过a标签链接点击到其他站点时...
- None:不做限制,即使是来自第三方的请求,也会发送Cookie,需要配合Secure属性一起使用。
第三方Cookie:非当前域名下的服务器设置的Cookie。例如上图中当前网页访问的是a.test.com网站, 请求了a.example.com的图片资源,a.example.com即为第三方。
SameSite改变的影响
在Chrome 80+版本中,SameSite的默认属性是SameSite=Lax,当Cookie没有设置SameSite属性时,将会视作Lax。如果想要指定Cookies在同站、跨站请求都被发送,那么需要明确指定SameSite为None。具有SameSite=None的Cookie也必须标记为安全并通过HTTPS传送。
同源(Same-Origin)&同站(Same-Site)
Same-Origin
协议(http/https)+主机+端口三者完全保持一致。例如https://juejin.cn/post/7338284106797088809#heading-9和https://juejin.cn/post/7355063847382810635符合同源标准。
Cross-Origin
Same-Origin规则中任意不一致即跨域,具体参考浏览器:安全策略。
Same-Site
两个URL的eTLD+1相同即可,不需要考虑协议和端口。eTLD表示有效顶级域名,注册于Mozilla维护的公共后缀列表(Public Suffix List)中,例如,.com、.co.uk、.github.io等。eTLD+1表示,有效顶级域名+二级域名。
例如:
- test.com和a.test.com同站
- test.com和example.com跨站
总结
- Web中任何请求都受到同源限制,Cookie在此基础上还会受到同站策略限制(samesite指定)。
- 跨站一定跨域,跨域不一定跨站。
- AJAX跨域请求一般有两个问题:请求能否发出去,Cookie能否携带上。
跨域携带Cookie解决方案
通过CORS解决
服务器端配置:在服务器端设置响应头Access-Control-Allow-Credentials为true,并且Access-Control-Allow-Origin不能为*,必须是请求方的具体源,如example.com。
客户端配置:发起请求时,设置credentials为include确保请求会携带Cookie。
通过代理服务器解决
如果不是我们自己业务的服务端,无法配置更改,可以通过代理转发的方案。
浏览器禁用第三方Cookie解决方案
设置samesite:none
设置跨站可以传递Cookie,需要配合Secure一起使用。
使用第一方Cookie
由主域直接设立和访问,不受第三方Cookie限制的影响。
代理服务器转发
如同上面的方案一样,这个情况也同样适用。
使用其他存储方案
Cookie的作用是存储用户标识,让服务端知道是谁在请求,我们可以使用其他的存储方式,例如localStorage。
follow浏览器标准
例如Partitioned属性,设置Cookie分区存储。它的作用是使第三方Cookie与第一方站点相绑定,通过将第三方Cookie的读取和写入操作限制在创建它们的相同网站的上下文中,来增强用户隐私。
分区前Cookie存储
因为a.test.com和a.example.com都使用了a.3rd.com的资源。a.3rd.com可以在请求时设置Cookie。这样当同一个用户在两个网站上活动时可以被a.3rd.com识别到,造成隐私泄露...
分区后Cookie存储
因为Cookie的存储方式变了,用户在a.test.com浏览时a.3rd.com设置的Cookie包含了当前的上下文。当用户在a.example.com访问时,因为[a.test.com,a.3rd.com]这个Cookie无法被访问到不会被自动发送给第三方服务器,阻止了第三方的信息采集,增强了用户的隐私保护...
跨域无法携带Cookie Vs 浏览器全面禁止第三方Cookie 区别
- 目的不同:跨域请求默认不携带Cookie主要是出于安全考虑,防止跨站点请求伪造等攻击;禁止第三方Cookie主要是出于隐私保护考虑,防止用户跨网站被追踪。
- 操作层面不同:跨域Cookie的发送需要通过适当的服务器和客户端配置来实现;第三方Cookie的禁用是由浏览器控制,影响所有第三方来源的Cookie。
这两者虽然都涉及到Cookie和浏览器的策略,但它们关注的重点、解决的问题和需要的配置都有所不同。