Cookie全知道

作者: 橙汁坤 | 来源:发表于2020-03-22 13:07 被阅读0次

    Chrome更新后你还不知道Cookie中的SameSite吗?

    Cookie是什么

    一个Cookie就是存储在用户主机浏览器中的一小段文本文件。Cookies是纯文本形式,它们不包含任何可执行代码。一个Web页面或服务器告之浏览器来将这些信息存储。

    Cookie由来

    一般来说HTTP 1.x,是无状态协议,那么同一个客户端连续多次发送请求给服务器,服务器也识别不出这是同一个客户端发送的请求。为了解决这个问题才有了Cookie。在第一次访问网站的时候,服务器响应请求后,会将Cookie放入到响应请求中,在浏览器第二次发请求的时候,会把Cookie带过去,服务端会辨别用户身份。

    Cookie 的设置

    那 Cookie 是怎么设置的呢?简单来说就是

    • 客户端发送 HTTP 请求到服务器
    • 当服务器收到 HTTP 请求时,在请求返回的 Response Headers 可以看到 Set-Cookie 字段。
    • 浏览器收到响应后保存下 Cookie
    • 之后对该服务器每一次请求中都通过 Cookie 字段将 Cookie 信息发送给服务器。

    Cookie 的属性

    image.png
    • name
      代表cookie的名字一个域名下绑定的cookie,name不能相同,相同的name的值会被覆盖掉。
    • value
      表示cookie的值,值得注意的是用 JavaScript 操作 Cookie 的时候注意对 value 进行编码处理。

    由于cookie规定是名称/值是不允许包含分号,逗号,空格的,所以为了不给用户到来麻烦,考虑服务器的兼容性,任何存储cookie的数据都应该被编码.

    • domain
      这个是指的域名,这个代表的是,cookie绑定的域名,如果没有设置,就会自动绑定到执行语句的当前域,统一个域名下的二级域名也是不可以交换使用cookie的,比如设置 .test.com,这样无论是 a.test.com 还是 b.test.com 都可以公用 Cookie。

    • path
      path 指定了一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送 Cookie 首部。path这个属性默认是'/',这个值匹配的是web的路由,举个例子:比如设置 Path=/blog,其实它会给/blog、/blogabc等等的都会带 Cookie 首部。/test 则不会携带 Cookie 。

    //默认路径
    www.test.com
    //blog路径携带Cookie
    www.test.com/blog
    //不携带
    www.test.com/test
    
    • expires
      expires 用于设置 Cookie 的过期时间。一般浏览器的Cookie都是默认储存的,当关闭浏览器结束这个会话的时候,这个cookie也就会被删除是会话性 Cookie,其值保存在客户端内存中。与会话性 Cookie 相对的是持久性 Cookie,持久性 Cookies 会保存在用户的硬盘中,直至过期或者清除 Cookie。而设定的日期和时间只与客户端相关,非服务端。
      举例来说:如果你想要cookie存在一段时间,那么你可以通过设置expires属性为未来的一个时间节点,expires代表当前时间。

    • Max-Age
      Max-Age 用于设置在 Cookie 失效之前需要经过的秒数。比如:

    Set-Cookie: id=a3fWa; Max-Age=604800;
    

    Max-Age 可以为正数、负数、甚至是 0。
    如果 max-Age 属性为正数时,浏览器会将其持久化,即写到对应的 Cookie 文件中。

    1. 当 max-Age 属性为负数,则表示该 Cookie 只是一个会话性 Cookie。
    2. 当 max-Age 为 0 时,则会立即删除这个 Cookie。
    3. 当 expires 和 Max-Age 都存在,Max-Age 优先级更高。
      不能跨域设置 Cookie,例如:在test的域名下设置
    Set-Cookie: qwerty=219ffwef9w0f; Domain=baidu.com; Path=/; Expires=Wed, 30 Aug 2020 00:00:00 GMT
    

    是无效的,因为domain 和path共同定义了 Cookie 的作用域。

    • Secure属性


      image.png

    http不仅是无状态的,还是不安全的协议,容易被劫持,当Secure属性设置为true时 Cookie 只会在https和ssl等安全协议下传输,其可以保护 Cookie 在浏览器和 Web 服务器间的传输过程中不被窃取和篡改。但是个属性并不能对客户端的Cookie进行加密,还是不能保证绝对的安全性。

    • HTTPOnly
      设置 HTTPOnly 属性可以防止客户端脚本通过 document.cookie 等方式访问 Cookie,有助于避免 XSS 攻击。

    • SameSite
      SameSite 属性可以让 Cookie 在跨站请求时不会被发送,从而可以阻止跨站请求伪造攻击(CSRF)。SameSite 有三种值:

    1. Strict :仅允许一方请求携带 Cookie,即浏览器将只发送相同站点请求的 Cookie,即当前网页 URL 与请求目标 URL 完全一致。
    2. Lax :允许部分第三方请求携带 Cookie
    3. None: 无论是否跨站都会发送 Cookie
      之前默认是 None 的,因为 2 月份发布的 Chrome80 版本中默认屏蔽了第三方的 Cookie,其SameSite默认是 Lax。跨站和我们熟悉的跨域是不同的

    js如何操作Cookie

    //读取浏览器中的cookie
    console.log(document.cookie);
    //写入cookie
    document.cookie='test=TestCookie;path=/;domain=.baidu.com';
    

    Cookie 的作用

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

    这里又引出一个问题:保存在服务器端的Session和Cookie又什么不同?又是怎么配合的的?先说几个不同:

    1. 有效期不同,Cookie 可设置为长时间保持,比如默认登录功能,Session 一般客户端关闭或者 Session 超时都会失效。
    2. 隐私策略不同,Cookie 存储在客户端;Session 存储在服务端,安全性相要好一些。
    3. 存储大小不同, 单个 Cookie 保存的数据不能超过 4K,Session 可存储数据远高于 Cookie。
    4. 存取方式的不同,Cookie 只能保存 ASCII,Session 可以存任意数据类型比如保持一些常用变量信息,比如说 UserId 等。

    Cookie 和 Session关联?

    Cookie 和 Session就是来告诉服务端,本次操作用户是否登录,是哪个用户在执行的操作。


    image.png

    用户第一次请求服务器的时候,服务器根据用户提交的相关信息,创建创建对应的 Session ,请求返回时将此 Session 的唯一标识信息 SessionID 返回给浏览器,浏览器接收到后会将此信息存入到 Cookie 中,同时 Cookie 记录此 SessionID 属于哪个域名。

    用户第二次访问服务器的时候,请求判断此域名下是否存在 Cookie 信息,如果存在自动将 Cookie 信息也发送给服务端,服务端会从 Cookie 中获取 SessionID,查找对应的 Session 信息,如果没有找到说明用户没有登录或者登录失效,如果找到 Session 证明用户已经登录可执行后面操作。

    总结一下:SessionID 是连接 Cookie 和 Session 的一道桥梁,大部分系统也是根据此原理来验证用户登录状态。

    既然上面说了SameSite 属性可以让 Cookie 在跨站请求时不会被发送,而服务端有需要 Cookie 中的信息判断用户是否登录,那么如何保障整个机制的正常运转?

    1. 每次请求中携带 SessionID ,也可以 Post 的方式提交,也可以在请求的地址后面拼接 xxx?SessionID=123456...。
    2. Token 机制。多用于 App 客户端和服务器交互的模式,也可以用于 做用户状态管理。Token就是是“令牌”,服务端生成的一串字符串,作为客户端进行请求的一个标识。Token 机制和 Cookie 和 Session 的使用机制比较类似。
      当用户第一次登录后,服务器根据提交的用户信息生成一个 Token,响应时将 Token 返回给客户端,以后客户端只需带上这个 Token 前来请求数据即可,无需再次登录验证。

    如何考虑分布式 Session 问题?

    为了可以支撑更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在 A 服务器登录了,第二次请求跑到服务 B 就会出现登录失效问题。
    分布式 Session 的解决一般有下面几种。

    1. Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。
    2. Session 复制,每当在一个服务器上的 Session 发生改变(增删改操作),该节点会把这个 Session 的所有内容广播给所有其它节点,实现状态一致。
    3. 共享 Session,服务端无状态化,将用户的 Session 等信息使用缓存中间件来统一管理,保障分发到每一个服务器的响应结果都一致。
    image.png

    举个例子可以使用redis实现分布式Session管理,客户端请求,经过Nginx负载均衡分发至tomcat实例,再经过Session管理,实现Session在redis中存取。配置redis主从集群,主redis数据热备份至从redis,当主redis宕机了,系统自动切换至从redis,从而保证系统缓存方面高可用建议这种方案。

    从Cookie到Session你所需要了解的信息就都在这里了。

    相关文章

      网友评论

        本文标题:Cookie全知道

        本文链接:https://www.haomeiwen.com/subject/epfpyhtx.html