Cookie是什么?cookies是你访问网站时创建的数据片段文件,
用来记录访问者的用户信息、历史记录、访问偏好、以及判定老访客的登陆状态,并且通过这些信息提升访问者在网站上的使用体验。
First-party cookies or Third-party cookies
第一方cookie由你访问的站点创建。该站点指的是地址栏显示的站点;
第三方cookie是由其他站点创建的。这些站点拥有你当前访问的网页上部分资源,如广告或图像。
第一方/第三方cookie不是绝对的标签,而是相对于用户的上下文,同一cookie可以是第一方也可以是第三方,这取决于用户当时所在的网站。
cookie的常规使用方式
web服务端发送给浏览器的cookie,浏览器会存储并在下次请求原服务器的时候回发cookie。
在HTTP请求模型中以标头的形式体现:Response中Set-Cookie
标头种植cookie;Request Cookie
标头携带(该请求允许携带的)cookies
HTTP/1.0 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: X-BAT-FullTicketId=TGT--******; path=/; samesite=none; httponly [page content]
Cookie
标头的内容是键值对(键值对才是具业务含义的cookie);同名cookie覆盖原键值,不同名cookie会追加到键值对。
GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; X-BAT-FullTicketId=TGT--******
除了服务端响应时使用Set-Cookie
标头种植cookie,浏览器JavaScript也可以种植cookie。
cookie的种植面积
Domain
和Path
属性定义了cookie的写入范围:哪些url的请求可以携带该cookie。
Domain
指定哪些host能被种植该cookie,如果没有指定,默认是当前document location所在的host,不包含子域;如果指定了Domain,那么包括子域(也就是说在该域名下共享cookie,这也是利用二级域名共享cookie实现单点登录的原理)。
例如设置了Domain=bat.com, 那么类似于developer.bat.com、xxoo.bat.com等子域下的url请求均会种下该cookie.
- Path 指定能携带该cookie的具体url。 "/" 是目录分隔符,会匹配子目录.
例如设置了Path =/doc,下面的目录都会被匹配.
- /docs
- /docs/web/
- /docs/web/http
cookie的有效时长
一般情况下浏览器关闭,cookie失效;
可通过设置特定的Expires或者Max-Age为cookie设置相对较长的有效时间。
Set-Cookie: id= a2faw; Expires=Wed, Oct : GMT
当设置了过期时间,这个设置的时间是相对于浏览器而言,而非服务器。
cookie与web安全息息相关
因为cookie是站点私有片段数据,与web上各种攻击密切相关,如XSS,CSRF.
根据W3c的操作规范,种植cookie时可通过某些属性限制cookie的使用方式。
发送cookie的物理安全
Secure
指定了发送cookie的物理安全:要求以HTTPS形式回发cookie。 Chrome52+、Firefox52+已经支持Secure指令,再使用http请求已经不会携带Secure cookie
。
即便是Secure指令, 敏感信息也不要放在cookie中, 因为他们天生就不安全,https并不能提供足够有效的安全防护。
谁能访问cookie?
web上能访问cookie的物件有两种:
浏览器请求
JavaScript
HttpOnly
指示cookie将不能通过JavaScript的document.cookie
编程接口访问,这样可以缓解对跨站点脚本(XSS
)的攻击。
如:访问会话在浏览器留置的认证cookie就没有必要暴露给JavaScript,可对其设置HttpOnly指令
Set-Cookie: X-BAT-FullTicketId=TGT--******; Expires=Wed, Oct :: GMT; Secure; HttpOnly
哪些浏览器请求能合法携带cookie?
首先科普一下重要的web HTTP知识:
对页面资源的请求,依据请求发起者的源Origin与资源的源Origin的相等关系,被划分为4类。
Http请求中Sec-Fetch-Site
标头指示了这个属性:
cross-site | 请求的发起源与资源源完全不相同 |
same-origin | 请求的发起源与资源源完全相同 |
same-site | 请求的发起源与资源源部分相同:同一顶级域名下的二级域名 |
none |
Q1. 域Domain、源Origin、站Site、傻傻分不清清楚?
观察www.cnblog.com任意一篇博文的network,看动图!
本人之前也被各种 域Domain、源Origin、站Site专属名称搞得很困惑?
Q2. 聊cookie为什么要提到给请求分类的Sec-Fetch-Site
标头?
答:B站页面在请求A站资源时能否携带A站cookie(第三方cookie
)不仅是一个道德问题;技术上还牵涉web安全(CSRF)。
针对以上的请求类型,浏览器针对cookie有SameSite
属性,提供针对跨站点请求伪造攻击(CSRF
)的保护。
在服务端Set-Cookie
种植cookie时,SmmeSite
属性值可指示浏览器是否可在后续的“同一站点”或“跨站点”请求中携带这些cookie
Set-Cookie: X-bat-FullTicketId=TGT--em4xx0faD1c4pbt*********k5Z0vN4uPOoEBWfGIP6l-bat-xxxxooo; path=/; samesite=none; httponly
有如下枚举值:
Lax : 对同源、顶级域的请求才可以携带cookie (等价于same-site)
Strict: 对同源请求才可以使携带cookie (等价于same-origin)
None: 对于cookie的使用无限制,随便使用
总之,IEEF配合浏览器给cookie的存取、传输规定了一套完整的策略,环环相扣,促进了web上cookie的平衡应用。
总结输出
第一方cookie vs 第三方cookie的认定: 取决于访客所处的上下文
cookie的常规用法,大家耳熟能详
根据源Origin、站Site、域Domain,请求被划分为4大类,关注HTTP
Sec-Fetch-Site
标头服务器在种植cookie时,可对cookie设置SameSite属性,故SameSite作用对象是cookie
SameSite属性决定了后续的跨域/跨站请求是否可以携带B站cookie,缓解了CSRF攻击
https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Sec-Fetch-Site
https://web.dev/samesite-cookies-explained