在 Web 开发中,HTTP 协议本身是无状态的。为了维持用户的登录状态(即状态信息),我们需要借助 Cookie、Session 或 Token 等机制。
状态信息的概念
状态信息指用户登录后,后续页面维持登录状态所需的信息。
-
原始方式(不推荐): 若不使用Cookie、Session 或 Token 等机制,用户需在每次请求中传递用户名和密码。服务端需反复鉴权(认证),确认无误后再传回前端。
-
弊端: 既不安全(密码频繁传输),又麻烦(每次请求都要携带)。
Cookie 的工作原理
Cookie 是一种将状态信息保存在**客户端(浏览器)**的机制。
- 工作流程
- 登录: 前端发起登录请求。
- 响应: 服务端认证成功后,将用户名等信息存入 Cookie,并通过响应头返回给前端。
- 存储: 浏览器自动保存这些信息。
- 后续请求: 浏览器会自动在所有后续请求中带上 Cookie,从而维持登录状态。
2. Cookie 的弊端
- 安全风险: 存储在客户端,用户可篡改(如修改 Cookie 中的用户名冒充他人)。虽然可以加密,但加密规则泄露仍有风险。
- 容量有限: 默认大小通常为 4KB,不适合存储大量数据,虽然可以通过浏览器修改。
- 依赖浏览器设置: 用户可通过浏览器禁用 Cookie,导致无法维持状态。因此不能完全依赖 Cookie 保持登录状态。
️ Session 的工作原理
Session 是一种将状态信息保存在服务端的机制,通常配合 Cookie 使用。
- 工作流程
-
登录: 前端将用户名密码传到后端。
-
创建 Session: 服务端认证成功后,将用户信息(甚至是整个用户对象)存入 Session。
-
返回 ID: 服务端生成唯一的 SessionID,通过响应头的
Set-Cookie属性返回给前端。 -
存储 ID: 前端自动将 SessionID 存入浏览器的 Cookie 中。
-
后续请求: 浏览器自动在请求头中带上包含 SessionID 的 Cookie。
-
验证: 服务端通过 SessionID 找到对应的 Session,获取用户信息,维持登录状态。
注意: Web 服务器(如 Tomcat)会自动处理 SessionID 的生成与传递,开发者只需关注往 Session 中存数据,前端无需额外操作。
-
2. Session 的优势
- 安全性高: 敏感数据存储在服务器端,客户端只持有 ID。
- 容量大: 服务端内存限制较小,可以保存复杂的对象数据。
- Session 的弊端
- 服务器压力: 存储在服务端,高并发时会占用大量服务器内存资源。
- 扩展性差(集群问题): 在负载均衡或集群部署下,Session 仅存在于某一台服务器。如果请求被分发到另一台服务器,将无法识别登录状态(需通过 Redis 等中间件解决 Session 共享问题)。
- 跨域问题: 在前后端分离架构(如移动端、小程序、不同端口)中,Cookie 默认不传递,配置跨域和允许 Cookie 传递较为麻烦。
Token 的工作原理(以 JWT 为例)
Token 是一种无状态的认证机制,客户端持有加密字符串,服务端不保存状态。目前最常见的是 JWT (JSON Web Token)。
- JWT 的结构
JWT 是一个加密字符串,由三部分组成,用点号分隔:
- Header(头部): 包含元数据,如签名算法(例如 HS256)和 Token 类型。
- Payload(负载数据): 包含实际数据(如用户名、用户ID)。这部分经过 Base64 编码,前端可以直接解码读取内容。
- Signature(签名): 安全的核心。由 Header、Payload 的编码结果结合服务端密钥,通过 Header 中指定的算法加密生成,用于防止篡改。
- 工作流程
- 登录: 前端发起登录请求。
- 签发: 服务端认证成功后,生成 JWT(包含上述三段信息)返回给前端。
- 存储: 前端自行存储 Token(如 LocalStorage)。
- 获取数据: 前端需要获取用户信息时,只需截取 Token 的第二段(Payload)进行 Base64 解码即可。
- 后续请求: 前端在请求头的
Authorization字段中带上 Token。 - 验证: 服务端接收 Token,利用密钥验证签名(确保未被篡改)并检查有效期。验证成功则放行。
3. Token 的优势
- 无状态: 不依赖服务端存储,服务端无需保存 Session 信息。
- 扩展性好: 非常适合集群部署和前后端分离架构。
- 跨域支持: 解决了 Cookie 的跨域限制问题,适用于多端(App、小程序等)。