一、认证(Authentication)
由于 HTTP 是无状态的协议,因此,需要各种通行证来证明身份。我们主要有以下几种方式的证明。
二、Cookie
1. 含义
服务器发送给客户端(浏览器)的小型文本数据片段,由客户端存储,用于跟踪用户状态。
2. 工作原理
由服务器产生,保存在客户端,下一次发送请求同一网址时会把 Cookie 给到服务器。
浏览器第一次访问服务器的时候,服务器不知道用户的身份,会给浏览器创建一个独特的身份标识数据(格式为 key=value
键值对),放到 set-cookie
字段中;当浏览器再请求该网站时,会把该 Cookie 连同请求网址一同提交给服务器。服务器通过检查 Cookie 辨认用户状态,也可根据需要修改 Cookie 内容。
3. 过程
- 客户端第一次访问服务器时,服务器生成 Cookie,放到响应头的
set-cookie
字段中给到客户端保存。 - 客户端再次访问服务器时,会在请求头中带上 Cookie,服务器通过比对 Cookie 进行鉴权。
如下图,第一次访问页面时,响应头中包含 set-cookie
;后续请求的请求头会带上与 set-cookie
内容一致的 Cookie 值。
4. 特点
- 存储在客户端(浏览器),大小限制约 4KB,只能存储文本。
- 可设置过期时间(
Expires
或Max-Age
):若未设置,默认为 “会话级”(关闭浏览器后删除)。 - 受域名限制:仅向设置 Cookie 的域名发送,不允许跨域访问(除非设置
SameSite=None
等属性)。
三、Session
含义
服务器端为每个用户会话创建的存储空间,用于保存用户的临时数据(如登录状态、购物车信息等),本质是 “服务器端的状态存储”。
工作原理
- 客户端首次请求服务器时,服务器为该用户创建一个唯一的
Session ID
(随机字符串),并在服务器端开辟一块内存(或数据库)存储该用户的 Session 数据(如用户信息)。 - 服务器将
Session ID
通过 Cookie 发送给客户端,客户端存储该 Cookie。 - 后续客户端请求时,会自动携带包含
Session ID
的 Cookie,服务器通过Session ID
找到对应的 Session 数据,从而识别用户身份。
特点
- 由服务器产生,存储在服务器端(内存、Redis、数据库等)(占用内存,可能增大服务器负担),客户端仅存储
Session ID
(通常在 Cookie 中)。 - 无大小限制,可存储复杂数据(对象、列表等)。
- 生命周期由服务器控制:默认 “会话级”(用户长时间不操作会超时删除),也可手动设置过期时间。
sessionid
的名字不是固定的。- 常用 Redis 存储。
Cookie 与 Session 区别
Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。客户端浏览器访问服务器时,服务器把客户端信息以某种形式记录在服务器上,这就是 Session。客户端浏览器再次访问时,只需从该 Session 中查找客户状态即可。
如果说 Cookie 机制是通过检查客户身上的“通行证”来确定身份,那么 Session 机制就是通过检查服务器上的“客户明细表”来确认身份。Session 相当于程序在服务器上建立的一份客户档案,客户来访时只需查询档案表即可。
四、Token
含义
服务器生成的一串加密字符串,作为客户端请求的 “身份凭证”,本质是 “无状态的认证令牌”。
工作原理
(1)无状态 Token(典型如 JWT)——目前主流的 Token 设计
特点:服务器不存储 Token,仅通过加密算法验证有效性。Token 存储在客户端。
a. 客户端使用账号密码登录时,服务器验证通过后,生成一个包含用户信息(如用户 ID、过期时间)的 Token(通常用 JWT 等算法加密),返回给客户端。
b. 客户端将 Token 存储在本地(Cookie、localStorage、sessionStorage 等)。
c. 后续请求时,客户端在请求头(如 Authorization: Bearer <Token>
)或参数中携带 Token,服务器接收后验证 Token 的有效性(解密、检查过期时间),无需查询数据库,验证通过则允许访问。
(2)有状态 Token
特点:服务器会将 Token 存储在数据库 / 缓存(如 Redis)中,验证时需查询比对。
a. 服务器生成随机 Token(如 UUID),关联用户信息后存入数据库,同时返回 Token 给客户端。
b. 客户端请求时携带 Token,服务器查询数据库,验证 Token 是否存在、是否有效(如未过期、未被吊销)。
两种设计的核心区别
维度 | 无状态 Token(如 JWT) | 有状态 Token(如随机字符串) |
---|---|---|
服务器存储 | 不存储,Token 本身包含验证信息 | 存储在数据库 / 缓存中 |
验证方式 | 解密 Token,检查签名和过期时间 | 查询数据库,比对 Token 有效性 |
优势 | 无服务器存储负担,适合分布式系统 | 可随时吊销 Token,安全性更灵活 |
劣势 | 难以主动吊销(除非维护黑名单) | 增加服务器存储和查询成本 |
典型场景 | 短期有效、无需频繁吊销的认证(如 APP 接口) | 需要强制登出、权限即时变更的场景(如后台系统) |
特点
- 由服务器产生,存储在客户端;无状态 Token 服务器无需保存,有状态 Token 服务器需存储(数据库 / 缓存)。
- 大小通常较小(取决于携带的信息),可跨域传递(不受 Cookie 的跨域限制)。
- 生命周期由 Token 本身的过期时间控制,通常需配合 “刷新令牌(Refresh Token)” 机制延长有效期。
Token 的引入
(1)引入背景
客户端频繁向服务端请求数据,服务端需频繁查询数据库验证用户名和密码,效率低下。Token 在此背景下应运而生。
(2)目的
- 减轻服务器压力:仅通过加密算法或缓存校验,大幅降低数据库访问频率,尤其在高并发场景下提升性能。
- 增强身份认证安全性:避免密码在每次请求中传输,降低被拦截的风险。
- 支持跨域和分布式系统:相比 Cookie+Session,更易在前后端分离、跨域 API、移动端等场景中使用。
五、Cookie、Session、Token 核心区别对比
维度 | Cookie | Session | Token(无状态) |
---|---|---|---|
存储位置 | 客户端(浏览器 / 本地文件) | 服务器端(内存 / 数据库等) | 客户端(Cookie/Storage 等) |
状态性 | 客户端保存状态 | 服务器端保存状态 | 无状态(服务器不保存状态) |
安全性 | 较低(易被 XSS/CSRF 攻击,需设置 httpOnly、Secure 等属性增强) | 较高(数据在服务器,仅暴露 Session ID) | 中等(依赖加密算法,若存储在 localStorage 易受 XSS 攻击) |
跨域支持 | 受同源策略限制(默认不允许跨域发送) | 依赖 Cookie 传递 Session ID,同 Cookie 跨域限制 | 支持跨域(可在请求头中携带,不受 Cookie 限制) |
服务器负担 | 无(数据在客户端) | 有(需存储和管理 Session 数据,分布式环境需共享 Session) | 无(仅验证 Token,无需存储) |
适用场景 | 存储少量用户偏好(如主题设置)、配合 Session 传递 Session ID | 服务器端需严格控制状态(如后台管理系统) | 前后端分离、移动端 APP、跨域 API、分布式系统 |
大小限制 | 约 4KB(各浏览器略有差异) | 无限制(取决于服务器存储) | 较小(通常 < 1KB,避免过大影响性能) |
六、典型使用场景总结
- Cookie:适合存储轻量、非敏感的客户端状态(如用户是否勾选 “记住我”、网站语言偏好),或作为 Session ID 的载体。
- Session:适合服务器端需要严格管理状态的场景(如银行系统、后台管理平台),但需注意分布式部署时的 Session 共享问题(需用 Redis 等中间件同步)。
- Token:适合前后端分离(如 Vue/React 项目)、跨域通信(如第三方 API 调用)、移动端 APP(iOS/Android)等场景,避免服务器存储状态的负担。
七、补充说明
- Cookie 是 Session 的 “载体”:多数情况下,Session 的
Session ID
通过 Cookie 传递,但也可通过 URL 参数传递(不推荐,安全性差)。 - Token 可替代 Session:在分布式系统中,Token 的无状态特性避免了 Session 的共享难题,是目前主流的 API 认证方案。
- 安全性需针对性增强:
- Cookie:设置
httpOnly
(防止 JS 读取,防 XSS)、Secure
(仅 HTTPS 传输)、SameSite
(防 CSRF)。 - Session:定期更换
Session ID
(防固定攻击),敏感操作二次验证。 - Token:使用 HTTPS 传输,避免包含敏感信息,及时吊销无效 Token。
- Cookie:设置
通过以上对比可见,三者的核心差异在于 “状态存储位置” 和 “适用场景”:Cookie 是客户端的轻量存储,Session 是服务器端的状态管理,Token 是无状态的跨域凭证。实际开发中需根据需求(如是否跨域、是否分布式、安全性要求)选择合适的技术。