前言
当你在访问推特的时候,每点击一个新的板块就可以实现自动跳转,每访问到别的板块,你的登录状态仍然是在线,你有没有好奇过,他们是如何实现登录状态的持续的?我们都知道HTTP协议是无状态协议,这意味着 每次客户端向服务器发送请求时,服务器都不会保留任何关于之前请求的信息。 这种设计使得HTTP协议具有简单、高效的特点,但同时也带来了一个显著的问题:如何在一系列请求之间保持用户的会话状态?
这就要说到最早的存储机制——————“Cookie-Session” 了。
什么是 Cookie-Session ?
在之前的文章中我们提到:Cookie,小饼干,是存储在浏览器内的一小段数据,容量一般是4KB左右,能存储用户的一些关键信息,可以设置信息的过期时间,在每次浏览器发送请求时,都会自动携带。
而 Session,它是存储在服务器的数据,通过唯一的 Session ID 与客户端 Cookie 关联。它能够存储较大的数据(取决于服务器),也可以设置过期时间。
而 Cookie-Session 就是这样一种基于 Cookie 和服务器端存储的会话管理技术,用于在 HTTP 无状态协议下保持用户登录状态和存储用户数据。 它是早期 Web 开发中最主流的身份验证方案之一,至今仍在许多传统系统中使用。
这个机制是如何运作的?
-
- 用户登录
- 首先是用户登录,用户通过浏览器输入账号密码,发送给服务器进行校验。
- 其次是服务器校验状态,校验通过后,从数据库拿到一些数据,并存储在session中(一般是你的个人信息,购物车的物品...),同时也会自身创建一些数据,通常是临时数据,其中包含
sessionID - 然后,将
sessionID利用Set-Cookie,将其保存在用户浏览器中
-
- 保持登录状态
- 后续对于相关网站的请求,都自动携带
cookie,也就把sessionID传递过去了 - 服务器拿到
sessionID,从数据库中进行搜索校验,确认用户身份,返回存储在session中的数据
-
- 退出登录
- 浏览器退出,服务器删除
Session,返回Set-Cookie使得Cookie失效。
登录时:
后来保持登录状态的时候,服务器就不会再向数据库发请求校验账号密码了,这个时候服务器会校验Cookie中所携带的SessionID,通过对应的SessionID返回对应的数据,比如Session中存储的数据可能是这样的:
{
{
"session_id": "a1b2c3d4e5f6", // 会话唯一标识(由服务器生成)
"user": {
"user_id": 123, // 用户ID(数据库主键)
"username": "alice", // 用户名(用于显示)
"email": "alice@example.com", // 邮箱(脱敏处理)
"role": "customer", // 用户角色(如 admin/customer)
"is_authenticated": true // 是否已登录
},
"cart": [ // 购物车商品列表
{
"product_id": 101,
"name": "无线耳机",
"price": 199.99,
"quantity": 2
},
{
"product_id": 205,
"name": "手机壳",
"price": 29.99,
"quantity": 1
}
],
"preferences": { // 用户个性化设置
"theme": "dark", // 主题(dark/light)
"language": "zh-CN", // 语言偏好
"font_size": "medium" // 字体大小
},
"security": { // 安全相关数据
"ip_address": "192.168.1.100", // 用户登录IP
"user_agent": "Chrome/120.0", // 浏览器标识
"expires_at": "2024-05-20T23:59:59Z" // Session过期时间
},
"metadata": { // 其他元数据
"created_at": "2024-05-18T10:00:00Z", // Session创建时间
"last_activity": "2024-05-18T14:30:00Z" // 最后活跃时间
}
}
}
只要服务器找到了你的session_id,它就能把这一大串数据返回给你。是不是很厉害!
弊端
它是最早用来解决HTTP无状态协议导致无法保持用户状态的方法,但是它仍然存在一些弊端:
比如,它对服务器的存储压力是很大的,Session的数据通常会存在服务器的内存或数据库中,高并发的时候会导致一些问题,比如:当用户量激增的时候服务器内存成本高,每次查询Session信息的时候,会触发高频的 I/O ,可能会导致反应迟缓。
例:100万用户在线 → 100万条 Session 数据 → 每秒数万次 Redis 查询。
其次呢,拓展性有点差,在分布式集群或微服务架构中,Session共享困难,如果Session被存储在 A 服务器中,当用户请求被负载均衡到服务器 B 时无法识别。
以上这些不好的风险,就催生了Token的诞生,这个我们将留到下一期详细讲解~
总结
OK,这一期我们详细讲解了Cookie-Session的机制:
在我们首次登录时,向服务器发送请求,服务器根据我们传入的账号密码在数据库中校验身份,随后在数据库中拿到相关信息,存储在服务器中,并给浏览器返回一个session_id,之后每一次访问同源的网站都会只校验session_id,并返回相关信息。
最后在用户登出的时候,服务器会删除Session的数据,并设置浏览器的Cookie为空。