Cookie AND Session
概述
参考:
Cookie
HTTP Cookie(也叫 Web Cookie 或浏览器 Cookie)是服务器发送到用户浏览器并保存在本地的一小块数据。浏览器会存储 cookie 并在下次向同一服务器再发起请求时携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器——如保持用户的登录状态。Cookie 使基于无状态的 HTTP 协议记录稳定的状态信息成为了可能。
背景
- HTTP 是无状态协议,服务器不能记录浏览器的访问状态,也就是说服务器不能区分两次请求是否由同一个客户端发出
- Cookie(小甜饼) 就是解决 HTTP 协议无状态的方案之一
- Cookie 实际上就是服务器保存再浏览器上的一段信息。浏览器有了 Cookie 之后,每次向服务器发送请求时都会同时将该信息发送给服务器,服务器收到请求后,就可以根据该信息处理请求
- Cookie 由服务器创建,并发送给浏览器,最终由浏览器保存
Cookie 的用途
- 保持用户登陆状态,由于不够安全,有其他方式替代,比如 JWT 等。
- 京东未登录的状态下,使用 Cookie 存储购物车中的物品的
淘宝不是这么实现的,淘宝必须登录才能浏览详细商品
- 上一次连接时打开的页面
- 与某个账号关联
- 等等
Cookie 的属性
一个 cookie 将会具有如下字段:
- name # cookie 的名称
- value# cookie 的值
- domain # 可以访问此 cookie 的域名
- path# 可以访问此 cookie 的页面路径。比如 domain 是 desistdaydream.ltd,path 是 /cookie,那么只有访问 http://desistdaydream.ltd/cookie 路径下的页面时,才可以读取此 cookie
- MaxAge或 Expires # 设置 cookie 持久化时的过期时长
- 注意:Expires 是老式的过期方法, 如果可以,应该使用 MaxAge 设置过期时间,但有些老版本的浏览器不支持 MaxAge。 如果要支持所有浏览器,要么使用 Expires,要么同时使用 MaxAge 和 Expires。
- size # cookie 的大小
- httpOnly # 是否允许别人通过 js 获取自己的 cookie
- httpOnly 属性限制了 cookie 对 HTTP 请求的作用范围。特别的,该属性指示用户代理忽略那些通过"非 HTTP" 方式对 cookie 的访问(比如浏览器暴露给 js 的接口)。
- secure # 是否只能通过 https 访问
注意:
- HttpOnly 属性和 Secure 属性相互独立:一个 cookie 既可以是 HttpOnly 的也可以有 Secure 属性。 在前段时间的项目中我就用 js 去读取一个 cookie,结果怎么都取不到这个值,最后查证这个 cookie 是 httpOnly 的,花了近 2 个小时,悲剧了。
Cookie 的缺点
- 不安全,明文
- 增加带宽消耗
- 可以在客户端手动禁用
- Cookie 是有上限的,最大 4096 字节
Session
背景
Cookie 虽然在一定程度上解决了 “保持状态” 的需求,但是由于 Cookie 本身最大支持 4096 字节,以及 Cookie 本身保存在客户端,可能被拦截或窃取,因此就需要有一种新的东西,它能支持更多的字节,并且他保存在服务器,有较高的安全性,这,就是 Session(会话)。
但是这时,问题又来了,基于 HTTP 协议的无状态特征,服务器根本不知道访问者是谁。又如何保存呢?此时,Cookie 又来了,起到了一个桥接的作用。
用户登录成功之后,我们在服务端为每个用户创建一个特定的 SessionData和 SessionID,他们一一对应。其中:
- SessionData 是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中
- 这个 SessionData 的数据结构一般都是 KEY/VALUE 类型的结构,相当于一个 **大 map。**可以保存在内存中、关系型数据库、Rdis、文件、等等地方
- SessionID 作为唯一标识符,通常会写入到用户的 Cookie 中。
所以,Session 必须依赖于 Cookie 才能使用,生成一个 SessionID 放在 Cookie 里传给客户端即可。
在互联网早期,访问一个网站为了持久化,将用户名和密码放在 cookie 里,一条信息就对应一条 cookie。
比如访问 baidu.com 后,浏览器记录了这么几个 cookie:
- username: DesistDaydream
- password: mypassword
- XXX: XXXX
- YYY: YYY
- …..等等
而使用了 Session 之后,Cookie 不再记录这些敏感信息,只保存一个 ID 用来标识这个 Session:
- sessionID: DesistDaydream
剩下的信息一般都保存在服务器本地,根据 sessionID 找到对应信息即可
Session 逻辑
这是一个简单的 Session 处理请求的逻辑
Session 设计思路
Session 本质上是一个 K/V ,通过 key 进行增删改查。可以存储在 RAM 或者 Redis 中。
- 一般有多个 Session,所以需要一个管理器统一管理
- Session 一般作为中间件,所以需要暴露结构给其他代码使用
Session 接口设计
- Set()
- Get()
- Del()
- Save() # 持久存储
SessionMgr 接口设计
- Init() # 初始化,加载 RAM 或 Redis
- CreateSession() # 创建一个新的 Session
- GetSession() # 通过 SessionID 获取对应的 Session 对象
RAM Session 设计
定义 RAM Session 对象
- SessionID
- 存 K/V 的 map
- 读写锁
构造函数,为了获取对象
- Set()
- Get()
- Del()
- Save()
RAM SessionMgr 设计
- 定义 Memory SessionMgr 对象
- 存放所有 Session 的 map
- 读写锁
- 构造函数
- Init()
- CreateSession()
- GetSession()
Redis Session 设计
- 定义 RedisSession 对象
- SessionID
- 存 K/V 的 map
- 读写锁
- Redis 连接池
- 记录内存中 map 是否被修改的编辑
- 构造函数
- Set()
- Get()
- Del()
- Save()
Redis SessionMgr 设计
- 定义 Redis SessionMgr 对象
- Redis 地址、密码、连接池、读写锁
- 存放所有 Session 的 map
- 读写锁
- 构造函数
- Init()
- CreateSession()
- GetSession()
反馈
此页是否对你有帮助?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.