Cookie是什么?cookies是你访问网站时创建的数据片段文件,

用来记录访问者的用户信息、历史记录、访问偏好、以及判定老访客的登陆状态,并且通过这些信息提升访问者在网站上的使用体验。

http请求协议中有三类元素可以传值: cookie, header, uri

要注意cookie 和header的区别:

- cookie 是有持久化能力的,且 具有域名domain亲和性的,有可能会被浏览器自动带上。

- header是需要编码请求时主动带上, 浏览器默认不会添加 请求头。

- uri是直接体现在请求的标记上。

第一方Cookie vs  第三方Cookie

第一方cookie由你访问的站点创建。该站点指的是地址栏显示的站点;

第三方cookie是由其他站点创建的。这些站点拥有你当前访问的网页上部分资源,如广告或图像。

第一方/第三方cookie不是绝对的标签,而是相对于用户的上下文,同一cookie可以是第一方也可以是第三方,这取决于用户当时所在的网站。

为什么要提第三方cookie,这与下面的cookie的SameSite策略密切相关。

cookie的常规使用方式

web服务端发送给浏览器的cookie,浏览器会存储并在下次请求原服务器的时候回发cookie。

回发以HTTP Response Set-Cookie 标头来体现, 通知浏览器种植cookie;

HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: X-BAT-FullTicketId=TGT-969171-******; path=/; samesite=none; httponly
[page content]

Request Cookie 标头携带(该请求允许携带的)cookies,

Cookie 标头的内容是 键值对 (键值对才是具业务含义的cookie);同名cookie覆盖原键值,不同名cookie会追加到键值对。

rfc文档显示 , cookie kv 属性名(attribute name ) 是区分大小写的, 也就是说 X-BAT-FullTicketId区分大小写。

GET /sample_page.html HTTP/1.1
Host: www.example.org
Cookie: yummy_cookie=choco; X-BAT-FullTicketId=TGT-969171-******

除了服务端响应时使用 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,21 Oct 2015 07:12 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-969171-******; Expires=Wed, 21 Oct 2020 07:28:00 GMT; Secure; HttpOnly

    哪些浏览器请求能合法携带Cookie?

    首先科普一下重要的web HTTP知识:

    对页面资源的请求,依据 请求发起者的源Origin与资源的源Origin的相等关系 ,被划分为4类。

    Http请求中 Sec-Fetch-Site 标头指示了这个属性, 这个标头的值有浏览器自己判断。

    Sec-Fetch-Site 描述 cross-site 请求的发起源与资源源完全不相同 same-origin 请求的发起源与资源源完全相同 same-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-178876-em4xx0faD1c4pbt*********k5Z0vN4uPOoEBWfGIP6l-bat-xxxxooo; path=/; samesite=none; httponly

    有如下枚举值:

    Lax : 对同源、顶级域的请求才可以携带cookie (等价于same-site)

    Strict: 对同源请求才可以使携带cookie (等价于same-origin)

    None: 对于cookie的使用无限制,随便使用

    最新的IEEF cookie SameSite策略:

    1.    敦促浏览器版本迁移,使cookie的SameSite默认= Lax( 如果没有设置SameSite属性,这个SameSite就默认是Lax

    2.   如果需要跨域发送cookie,请使用None枚举值选择 无SameSite限制 , None指令需要搭配 Secure 指令 ( 如果使用SameSite=None, 但是不带secure,那么这个cookie将被丢弃 )

    Tip : None枚举值是标准新增枚举值,一些旧浏览器不识别这个枚举值,可能导致一些问题.

    总之,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攻击

    1. cookie片段的键是区分大小和 特性的。

    eg:  userinfo  userInfo 是不同的cookie;

    userInfo=%7B%22CTIDS%22%3A%220583d%22%2C%22GID%22%3A%22GIDU306R3%22%2C%22MTID%22%3A%2205;domain=x.baidu.com

    userInfo=%7B%22CTIDS%22%3A%220583d%22%2C%22GID%22%3A%22GIDU306R3%22%2C%22MTID%22%3A%2205;domain=www.baidu.com

    也是不同的cookie片段

    2.  document.cookie  拿到的是所有的cookie片段。

    3.  document.cookie ="key1=val1"      -- 如果 key1没有同名cookie键, 那么实际会产生追加cookie片段的效果

    4.  document.cookie ="kay1=val"       -- 存在同名cookie键, 产生修改cookie片段的效果。

    5.   清除某个cookie片段- 需要设置过期时间为当前之前: document.cookie ="key1==; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/"