• Cookie简介


    什么是Cookie

    Cookie 是服务器发送给浏览器,由浏览器保存在本地的一些数据,在浏览器向目标服务器再次发起请求时,浏览器会携带Cookie domain与目标服务器domain相同或Cookie domain为目标服务器的父域名的cookie。

    为什么需要Cookie

    Cookie存在的意义要从HTTP协议说起,HTTP协议是一个无状态协议。无状态的含义就是客户端的每个请求对服务器来说都是全新的,即使客户端在前一秒发送请求告诉服务器我是userA,下一秒再发送请求时,服务器会响应,但是它不知道当前请求还是来自userA的。每个请求都是独立的,上一个请求和下一个请求之间是没有任何联系的。

    HTTP协议设计为无状态的,主要是因为服务器需要面向全世界数十万、上百万的用户,而每个客户端(即浏览器)与服务器之间交换数据的间歇性较大(即传输具有突发性、瞬时性),并且网页浏览的联想性、发散性导致两次传送的数据关联性很低,大部分连接实际上会很空闲、无端占用资源。因此 HTTP 的设计者针对用户访问服务器的这些特点将协议设计为发起请求时建立连接、请求结束时释放连接,以尽快将资源释放出来服务其他客户端。

    HTTP协议的无状态就带来了一些问题,比如我们通过用户名密码登录了网站,后续再次发请求给服务器时,服务器并没有办法识别到我们在上一个请求中提供的用户信息,除非我们在请求中再次携带用户信息。如果服务器想要识别客户端的身份,那就需要通过一些方法将客户端的身份信息记录下来。目前,有两种解决方案,那就是Cookie和Session。

     Cookie是通过客户端保存状态信息的解决方案。从定义上来说,Cookie就是由服务器发给客户端的特殊信息,这些信息中会包含客户端的身份信息,客户端在收到这些信息后会以文本文件的方式保存在客户端,之后客户端每次向服务器发送请求的时候都会在Cookie Header中带上这些信息。服务器在接收到来自客户端浏览器的请求之后,就能够通过分析Cookie Header中的信息得到客户端的身份信息。像很多网站的登录界面中的“请记住我”的功能就是通过Cookie实现的。 

    Session是通过服务器保存状态信息的解决方案。当客户端访问服务器时,服务器会创建Session并保存在服务器上,同时将标识 Session 的 SessionId 返回给客户端浏览器,浏览器将这个 SessionId 保存起来,当客户端再次发送请求的时候,会将这个SessionId带上,服务器接受到请求之后就会依据SessionId找到相应的Session,从而获取到用户信息。这里SessionId在客户端的保存方式有多种,Cookie,Local Storage, Session Storage,页面隐藏表单等都可以。但还是用Cookie比较方便,不需要额外的处理,在发送请求的时候可以自动携带。所以归根结底,服务器想要获取状态信息都离不开Cookie。

    Cookie的应用

    Cookie 主要用于以下三个方面:

    • 会话状态管理(如用户登录状态、购物车、游戏分数或其它需要记录的信息)
    • 个性化设置(如用户自定义设置、主题等)
    • 浏览器行为跟踪(如跟踪分析用户行为等)

    Cookie 最主要的作用就是对请求和响应的状态进行管理, 服务端通过在响应体中设置 Cookie (状态), 客户端会将 Cookie (状态) 存储起来, 之后客户端给向该服务器发起的每个请求,浏览器都会自动将 Cookie (状态)带上, 这样服务端就能够对客户端的身份进行识别。

    Cookie是如何工作的

    Set-Cookie Response Header:服务器端用于给客户端设置Cookie

    1. HTTP/2.0 200 OK
    2. Content-Type: text/html
    3. Set-Cookie: yummy_cookie=choco
    4. Set-Cookie: tasty_cookie=strawberry

    Cookie Request Header:客户端用于向服务器端发送Cookie,服务器端设置Cookie之后,在Cookie过期之前,客户端发送给服务器端的每个请求都会自动带上这些Cookie。

    1. GET /sample_page.html HTTP/2.0
    2. Host: www.example.org
    3. Cookie: yummy_cookie=choco; tasty_cookie=strawberry

    Set-Cookie的使用

    1. Set-Cookie: <cookie-name>=<cookie-value>
    2. Set-Cookie: <cookie-name>=<cookie-value>; Expires=<date>
    3. Set-Cookie: <cookie-name>=<cookie-value>; Max-Age=<number>
    4. Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>
    5. Set-Cookie: <cookie-name>=<cookie-value>; Path=<path-value>
    6. Set-Cookie: <cookie-name>=<cookie-value>; Secure
    7. Set-Cookie: <cookie-name>=<cookie-value>; HttpOnly
    8. Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict
    9. Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax
    10. Set-Cookie: <cookie-name>=<cookie-value>; SameSite=None; Secure
    11. // Multiple attributes are also possible, for example:
    12. Set-Cookie: <cookie-name>=<cookie-value>; Domain=<domain-value>; Secure; HttpOnly

    Cookie的生命周期

    Cookie的生命周期有两种:  第一种是会话cookie    第二种是 持久cookie 

    • 会话Cookie:  如果没有设置过期时间  那么Cookie的生命周期与当前会话的生命周期相同,而会话的生命周期由游览器决定。一般来讲,当前浏览器窗口关闭,会话就是结束,Cookie也随之失效。但是有一些浏览器有Session Restore功能,可以使会话Cookie无限期保存。
    • 持久Cookie: 如果在服务器在Set-Cookie时通过Expries属性设置过期时间,或者通过Max-Age属性设置以秒为单位的存活时间,那么浏览器就会将将这个Cookie保存在客户端的硬盘上,在过期时间之前,再次访问同一个网站的时候,会将信息通过请求头Cookie发送给服务器。
    • Expires/Max-Age用于指定Cookie 的过期时间,过了这个时间之后 Cookie 将会自动删除。在过期时间之后再次向服务器发送请求时,将不会携带已过期的Cookie信息。
    • Expires设置过期的具体时间
    • Max-Age以秒为单位,设置多长时间之后过期
    1. Set-Cookie: id=a3fWa; Expires=Thu, 31 Oct 2021 07:28:00 GMT;
    2. Set-Cookie: id=a3fWa; Max-Age=3600

    限制Cookie的访问

    • 可以通过Secure和HttpOnly两种方式来保证Cookie的安全,保证Cookie安全的发送到客户端,防止被其他恶意脚本获取

    HttpOnly

    • 为避免跨域脚本 (XSS) 攻击,通过 JavaScript 的 Document.cookie API 无法访问带有 HttpOnly 标记的 Cookie,它们只应该发送给服务端。

    • 如果包含服务端 Session 信息的 Cookie 不想被客户端 JavaScript 脚本调用,那么就应该为其设置 HttpOnly 标记。

    Secure

    • 标记为 Secure 的 Cookie 只应通过被 HTTPS 协议加密过的请求发送给服务端,如果使用HTTP请求(localhost除外),则Cookie不会发送给服务器。

    • Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly

    限制Cookie的发送

    Domain

    Domain 标识指定了浏览器在向哪些服务器发送请求时可以携带该 Cookie。如果不指定,默认为与当前页面的domain相同的服务器(不包含子域名)。如果指定了 Domain,则浏览器在给指定的Domain以及其子域名发送请求时都会携带该Cookie。

    例如设置了 Domain=mozilla.org,则 浏览器在给mozilla.org或者developer.mozilla.org发送请求时都会携带该Cookie

    Set-Cookie: id=a3fWa; Domain=mozilla.org

    Path

    Path 标识指定了给服务器的哪些URL 路径发送请求时会携带该 Cookie。以字符 %x2F (/) 作为路径分隔符,子路径也会被匹配。

    设置 Path=/docs,则以下地址都会匹配:

    • /docs
    • /docs/Web/
    • /docs/Web/HTTP

    以下路径不会被匹配

    • /
    • /docsets
    • /fr/docs
    Set-Cookie: id=a3fWa; Path=/docs

    SameSite

    首先来理解一下SameSite的含义,同源协议中的源是由「协议+域名+端口」三者一起定义的,有一个不同就不算同源,而同站只受域名的约束,并且还不要求一模一样——只要「有效顶级域名+二级域名」相同,都算同站。比如https://baidu.com,https://www.baidu.com,https://passport.baidu.com属于不同源,但是属于同站。

    SameSite Cookie 允许服务器要求某个 Cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。

    Set-Cookie: key=value; SameSite=Strict
    • None :浏览器会在同站请求、跨站请求下继续发送 Cookies,不区分大小写;
    • Strict :浏览器在发送请求时只包含那些Cookie Domain与目标服务器Domian相同或是Cookie Domain是目标服务器的父Domain的Cookie
    • Lax 在新版本浏览器中,为默认选项,Same-site Cookies 将会为一些跨站子请求保留,如图片加载或者 iframe 不会发送,而点击 标签会发送;

     

    请求类型示例正常情况Lax
    链接发送 Cookie发送 Cookie
    预加载发送 Cookie发送 Cookie
    GET 表单
    发送 Cookie发送 Cookie
    POST 表单发送 Cookie不发送
    iframe发送 Cookie不发送
    AJAX$.get("...")发送 Cookie不发送
    Image发送 Cookie不发送
    • 以下图为例,比如当前用户在segmentfault的页面上,查看当前域名(注意这个域跟Cookie中的域不是一个意思)的cookie,可以看到Cookie的domain有.google.co.jp,.google.com,.segmentfault.com, .sponsor.segmentfault.com。
    • 在sponsor.segmentfault.com的页面上发送请求到segmentfault.com
      • 顶级域名和二级域名相同,同站,
      • 会携带Domain为.segmentfault.com的所有Cookie,包括SameSite=None,SameSite=Strict,SameSite=Lax
      • 不会携带Domain为.sponsor.segmentfault.com的Cookie,父域名不能使用子域名的Cookie
    • 在sponsor.segmentfault.com的页面上发送请求到sponsor.segmentfault.com
      • 域名完全相同,同站
      • 会携带Domain为.segmentfault.com的所有Cookie,包括SameSite=None,SameSite=Strict,SameSite=Lax,子域名可以使用父域名的Cookie
      • 会携带Domain为.sponsor.segmentfault.com的所有Cookie,包括SameSite=None,SameSite=Strict,SameSite=Lax,
    • 在sponsor.segmentfault.com的页面上发送请求到google.com
      • 二级域名不同,不同站
      • 不会携带Domain为.segmentfault.com的Cookie
      • 不会携带Domain为.sponsor.segmentfault.com的Cookie
      • 会携带Domain为.google.com且SameSite=None的Cookie
      • 不会携带Domain为.google.com且SameSite=Strict的Cookie,因为请求来源的站与目标站不是同一个

    Cookie共享

    前面已经介绍了可以通过Domain属性设置给哪些服务器发请求时可以携带该Cookie。

    如果Cookie设置了Domain属性,则给Domain指定的域及其子域发送请求时,都会携带该Cookie。比如上图中,给sponsor.segmentfault.com发请求时会携带Domain为.segmentfault.com的所有Cookie。

    总结来说就是:

    • 父域名的Cookie可以共享给子域名
    • 子域名的Cookie不可以共享给父域名
    • 父域名的服务器无法通过Set-Cookie设置Domain为子域名的Cookie,比如在segmentfault.com的相应头中设置name=sub;domain=sponsor.segmentfault.com,这个是无效的,浏览器不会认可。

    第一方Cookie与第三方Cookie

    • 如果Cookie 的Domain和当前页面的Domain同站,且当前页面的Scheme符合Cookie 的HttpOnly的属性配置,则认为当前Cookie与页面属于同一站点,并将该Cookie称为第一方 Cookie。
    • 如果Cookie 的Domain和当前页面的Domain不同站,或者Cookie设置了HttpOnly,但当前页面是HTTP,而不是HTTPS,则认为当前Cookie与页面属于不同站点,并将该Cookie称为第三方 Cookie。
    • 一般托管网页的服务器会设置第一方 Cookie,但该页面可能包含存储在其他域中的服务器上的图像或其他组件(例如,广告横幅),这些其他域的服务器可能会设置第三方 cookie。
    • 第三方Cookie主要用于网络上的广告和跟踪。
    • 以下图为例,对于.segmentfault.com来说,.segmentfault.com和sponsor.segmentfault.com都属于第一方Cookie,google.com属于第三方Cookie。

    参考

    Using HTTP cookies - HTTP | MDN

  • 相关阅读:
    ==和equals()的区别
    半回文数【Python】
    Flutter中Widget的生命周期
    springboot银行客户管理系统毕业设计源码250903
    JMeter + Ant + Jenkins持续集成-接口自动化测试
    图片、视频修复并超分 - Real-ESRGAN项目使用(一) | 机器学习
    西安交大最新综述!一文带你读懂大模型智能体及其组网与安全
    Vert.X CompositeFuture 用法
    计算机网络 八股
    活动回顾 | 基于英特尔技术的端到端音视频优化
  • 原文地址:https://blog.csdn.net/meiyubaihe/article/details/127836119