
Session 和 Token 都是 Web 应用中用于管理用户身份认证和会话状态的机制,但它们在存储位置、工作方式、扩展性、安全性等方面有本质区别。下面从多个维度详细对比。
1. 概念与工作原理
Session(会话)
-
定义:Session 是服务器端为每个用户创建的临时数据存储空间,用于保存用户的状态信息(如登录状态、用户ID、权限等)。客户端通过一个唯一的 Session ID 来关联自己的会话。
-
工作流程:
-
用户登录后,服务器生成 Session 数据并存储(内存、数据库或 Redis 等),同时创建一个唯一的 Session ID。
-
服务器将 Session ID 通过 Cookie 返回给客户端(通常名为 JSESSIONID)。
-
后续请求,浏览器自动携带该 Cookie,服务器根据 Session ID 查找对应的 Session 数据,从而识别用户。
-
特点:有状态 —— 服务器保存了所有用户的会话信息。
Token(令牌)
-
定义:Token 是一种自包含的凭证,通常采用 JWT(JSON Web Token)格式,将用户信息、权限、过期时间等加密签名后存放在客户端。服务器无需存储会话数据,只需验证 Token 的签名和有效性。
-
工作流程:
-
用户登录成功后,服务器生成一个 Token(包含用户标识和过期时间),返回给客户端。
-
客户端将 Token 存储(如 localStorage、sessionStorage 或内存),并在后续请求的 HTTP 头中携带:Authorization: Bearer <token>。
-
服务器从请求头中提取 Token,验证签名和有效期,解析出用户信息后执行相应逻辑。
-
特点:无状态 —— 服务器不保存任何会话数据。
2. 核心区别对比表
| 存储位置 | 服务器端存储会话数据,客户端仅存 Session ID | 客户端存储完整的 Token 数据,服务器无存储 |
| 状态 | 有状态(Stateful) | 无状态(Stateless) |
| 扩展性 | 水平扩展需共享 Session(如使用 Redis 集中存储),否则需粘性会话 | 天然支持水平扩展,服务器无需共享状态 |
| 跨域支持 | 受限于 Cookie 的同源策略,跨域需特殊配置(CORS + withCredentials) | 通过 HTTP Header 传输,天然支持跨域 |
| 安全性 | Session ID 泄露可能导致会话劫持; 可通过 HttpOnly、Secure 等 Cookie 属性增强安全 |
Token 若被窃取,攻击者可冒充用户直到过期; 签名防止篡改,但 payload 明文可见(不存敏感信息) |
| 性能 | 每次请求需查询会话存储(内存/Redis),可能产生 I/O 开销 | 验证 Token 仅需计算签名(CPU 密集型),无需查询存储,但 Token 体积较大增加网络开销 |
| 单点登录(SSO) | 实现复杂,需集中会话存储 | 易于实现,Token 可在多个服务间共享验证 |
| 过期控制 | 服务器可主动销毁 Session(如登出、超时) | 服务端无法主动使 Token 失效,需依赖短有效期 + 刷新机制或黑名单 |
| 适用场景 | 传统 Web 应用,对实时状态控制要求高(如强制下线) | 分布式/微服务架构、移动端、前后端分离、第三方 API 授权 |
3. 详细解析
3.1 存储位置与状态
-
Session:服务器保存用户数据,意味着需要占用服务器内存或外部存储(如 Redis)。当用户量巨大时,会话存储会成为瓶颈。同时,由于服务器保存状态,如果有多台服务器,必须共享会话数据(通过粘性会话或集中存储),否则请求落到不同服务器会导致无法识别用户。
-
Token:所有信息都放在客户端,服务器只需验证签名。这使得服务器完全无状态,任何服务器节点都可以独立处理请求,天然适合微服务和水平扩展。
3.2 安全性考量
-
Session:Session ID 通常存储在 Cookie 中,可以设置 HttpOnly(防止 XSS 窃取)、Secure(仅 HTTPS 传输)、SameSite(防止 CSRF)等属性,相对安全。但 Session 固定攻击、会话劫持仍需防范。
-
Token:JWT 的 Payload 是 Base64Url 编码,并非加密,因此不能存放密码等敏感信息。Token 泄露后,攻击者可在有效期内任意使用,服务端无法主动撤销(除非维护黑名单,但这就回到了有状态)。因此 Token 的有效期通常较短,并配合 Refresh Token 机制。
3.3 性能与网络开销
-
Session:每次请求需要根据 Session ID 查找会话数据(可能查内存或 Redis),有轻微 I/O 开销。但 Session ID 本身很小,网络传输量小。
-
Token:验证只需要计算签名(CPU 密集型),但 Token 本身可能较大(尤其包含较多 Claims),增加每次请求的带宽消耗。
3.4 过期与注销
-
Session:服务器可以主动销毁 Session(如用户登出、管理员强制下线),实时生效。
-
Token:由于服务端不保存状态,一旦签发,在过期前始终有效。若需提前失效,可采用短期 Token + Refresh Token 轮换,或维护一个黑名单(如 Redis 存储已注销的 Token),但这样又引入了状态。
3.5 跨域与多端支持
-
Session:依赖 Cookie,而 Cookie 默认受同源策略限制,跨域请求需配置 CORS 并设置 withCredentials,且第三方 Cookie 可能被浏览器限制。
-
Token:通过自定义 Header 传输,不依赖 Cookie,因此天然支持跨域,也适用于移动端、桌面应用等非浏览器环境。
4. 适用场景建议
选用 Session:
-
传统服务器渲染的 Web 应用(如 JSP、Thymeleaf)。
-
对实时状态控制要求高(如强制踢人、在线用户列表)。
-
对安全性要求极高,可利用 Cookie 的 HttpOnly 等特性防止 XSS 窃取。
-
用户量不大,或已有成熟的会话共享方案(如 Redis)。
选用 Token(JWT):
-
前后端分离的单页应用(SPA)、移动 App。
-
微服务架构,需要无状态认证,便于服务独立扩展。
-
第三方 API 授权(如 OAuth2 使用 JWT 作为 Access Token)。
-
需要跨域访问多个域名或服务的场景。
5. 总结
-
Session 是“服务器记住我”:服务器存储状态,客户端只持有一个钥匙(Session ID)。优点是可控性强、实时失效;缺点是有状态,扩展复杂。
-
Token 是“客户端证明我”:客户端持有经过签名的身份凭证,服务器只需验证。优点是无状态、易扩展、跨域友好;缺点是难以主动失效,且需妥善保管。
实际开发中,两者并非完全互斥,例如可以使用 Session 做传统 Web 认证,同时为 API 提供 Token 认证;或者使用 Redis 存储 Session 实现分布式,也可以将 JWT 与黑名单结合实现可控失效。选择哪种机制需根据具体业务需求、架构风格和安全要求综合权衡。







