周分享

Cookie全知道

2020-03-22  本文已影响0人  橙汁坤

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

Cookie是什么

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

Cookie由来

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

Cookie 的设置

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

Cookie 的属性

image.png

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

//默认路径
www.test.com
//blog路径携带Cookie
www.test.com/blog
//不携带
www.test.com/test
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 的作用域。

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

  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你所需要了解的信息就都在这里了。

上一篇 下一篇

猜你喜欢

热点阅读