![908e9a0568ed7b058959a03b2ffc616b.png](https://img-blog.csdnimg.cn/img_convert/908e9a0568ed7b058959a03b2ffc616b.png)
今天下雨,打不了球了: ( (周日写的,修改了下)
看了会 HTTP 的 Cookie 知识,记录一下。
Cookie 的起源
因为 HTTP 是无状态的,服务器不知道将多个商品添加到购物车的是不是同一个用户。为了解决这个问题,网景的工程师 Lou Montulli 发明了 Cookie。
工作原理
1. 浏览器发送用户凭证
2. 服务器验证通过后创建一个 Session,并返回一个 SessionID 交由浏览器存到本地 Cookie 里
3. 第二次请求时,浏览器会检查本地是否包含请求域名的对应 Cookie,如果有自动带着发给服务器
4. 服务器检查浏览器发过来的 SessionID,进行判断
常见字段
我们启动一个 node 服务来了解一下 Cookie 里面的各个字段:
// 导入 http 内置模块
毕竟也是持久化的一种,所以 Cookie 是存在于 Application 下的 Storage 里面,红框里就是常见的几个字段。
![26742bf28295dd7558df2a032f1784e3.png](https://img-blog.csdnimg.cn/img_convert/26742bf28295dd7558df2a032f1784e3.png)
我们分别看下:
- name、value
这个就是键值对:
![198fe3a8b482ed67808d34f5c6d2812b.png](https://img-blog.csdnimg.cn/img_convert/198fe3a8b482ed67808d34f5c6d2812b.png)
这里我看 [MDN](Set-Cookie)有这么一句话:
![89d720a93b3cb679659b3da9daf3e885.png](https://img-blog.csdnimg.cn/img_convert/89d720a93b3cb679659b3da9daf3e885.png)
但是我在 Chrome 里面的确可以用括号的,浏览器支持。
- domain
这个字段是指定 cookie 可以送达的主机名。域名之前的点号会被忽略。假如指定了域名,那么相当于各个子域名也包含在内了。我查看了 GitHub.com 的 Cookie,它的 domain 有的是 .github.com 有的是 github.com,其实只需要设置 github.com 就行了。而且它输入 www.github.com 也会重定向到 github.com。
还有一点是这里提到的是域名,并不包含端口,所以不同端口也可以共享这个 Cookie。我们可以验证下,本地再启动一个 4000端口:
// 导入 http 内置模块
访问一下,可以看到同样有这个 Cookie:
![38e98e0794cab72ccc8d112271d3c73e.png](https://img-blog.csdnimg.cn/img_convert/38e98e0794cab72ccc8d112271d3c73e.png)
- path
这个字段指定一个 URL 路径,这个路径必须出现在要请求的资源的路径中才可以发送 Cookie 首部。一般我们都默认设置为 `/`。
下面我们设置一个路径测试下:
// 导入 http 内置模块
如下图所示,当我们访问 /doc 这个路径时,Cookie 是有的。但是访问 /doc1 这个路径,Cookie 就没有了。
![f9301488e934761515c9b525bd1609d0.png](https://img-blog.csdnimg.cn/img_convert/f9301488e934761515c9b525bd1609d0.png)
![efcf5a8dd1e0a51e217a7fc5746556b5.png](https://img-blog.csdnimg.cn/img_convert/efcf5a8dd1e0a51e217a7fc5746556b5.png)
- Expires、MaxAge
Expires 和 MaxAge 是两个作用相同的字段,所以 Chrome 把它们两个放一起了。它们的格式不一样, Expires 的格式是 Date 格式,而 Max-Age 是数字形式的多少秒。
Expires 是 HTTP 1.0 的首部字段,因为客户端和服务端时间误差过大导致问题,所以才有 HTTP 的 Max-Age 字段。
默认值是 Session,意味着只是在当前会话保存该 Cookie:
![775a4bad3f0f30c5a06dbd5e688920a8.png](https://img-blog.csdnimg.cn/img_convert/775a4bad3f0f30c5a06dbd5e688920a8.png)
这里注意一个问题,这里设置的不是本地时间,所有可能有 Cookie 没有过期的情况,因为这个时间并没有过服务器的时间呢:
res
![ee44279d0be086075d843fd6dd289a95.png](https://img-blog.csdnimg.cn/img_convert/ee44279d0be086075d843fd6dd289a95.png)
![7f5e8745cb3fee8b827ae55af0c471ac.png](https://img-blog.csdnimg.cn/img_convert/7f5e8745cb3fee8b827ae55af0c471ac.png)
- Size
这个没什么好说的,就是 name 和 value 的大小之和:
![8e4381c93a7639dd82649c6a3185c6c0.png](https://img-blog.csdnimg.cn/img_convert/8e4381c93a7639dd82649c6a3185c6c0.png)
- HttpOnly
这个是防止遭受了 XSS 攻击之后不让别人获取 Cookie。
注意,这个可不能防止 XSS 攻击,只是降低损失,不让他做一些操作而已。
res
![2f04d166553f9f1dfed517e87a02f01c.png](https://img-blog.csdnimg.cn/img_convert/2f04d166553f9f1dfed517e87a02f01c.png)
- Secure
见字识意,就是在 SSL 和 Https 的时候才能传输 Cookie。的确设置了之后前端也是没有这个 Cookie 的。
- SameSite
这个主要是为了避免 CSRF 攻击,这个比较麻烦,就不举例了,有机会专门总结一下 CSRF。
进阶
这部分是别人写的,应该是后端的范畴了,顺便了解一下。
如何考虑分布式 Session 问题?
在互联网公司为了可以支撑更大的流量,后端往往需要多台服务器共同来支撑前端用户请求,那如果用户在 A 服务器登录了,第二次请求跑到服务 B 就会出现登录失效问题。
分布式 Session 一般会有以下几种解决方案:
Nginx ip_hash 策略,服务端使用 Nginx 代理,每个请求按访问 IP 的 hash 分配,这样来自同一 IP 固定访问一个后台服务器,避免了在服务器 A 创建 Session,第二次分发到服务器 B 的现象。
Session 复制,任何一个服务器上的 Session 发生改变(增删改),该节点会把这个 Session 的所有内容序列化,然后广播给所有其它节点。
共享 Session,服务端无状态话,将用户的 Session 等信息使用缓存中间件来统一管理,保障分发到每一个服务器的响应结果都一致。
(完)
参考资料
- [MDN](Set-Cookie)
- [你真的了解 Cookie 和 Session 吗](你真的了解 Cookie 和 Session 吗)