计算机网络:Cookie、Session、Token 的区别是什么?
一句话:Cookie 是浏览器端的存储与自动回传载体,Session 是服务端保存的会话状态,Token 是服务端签发、客户端自带的凭证。 面试真正考的不是名词解释,而是三件事:状态放在哪一侧、谁负责校验、失效能多快生效。
1. 三者不在同一层
Cookie 是 HTTP 的状态管理机制,Session 和 Token 是"会话方案",它们都可以借 Cookie 落地,也都可以不用 Cookie。
| 维度 | Cookie | Session | Token |
|---|---|---|---|
| 本质 | 键值文本 + 自动回传 | 服务端的一条会话记录 | 带签名的自包含串 |
| 状态位置 | 客户端 | 服务端内存 / Redis / 数据库 | 客户端,服务端只验签 |
| 服务端开销 | 无 | 每次请求查一次存储 | 一次 HMAC 或验签运算 |
| 跨域能力 | 受同源与 SameSite 限制 | 依赖 Cookie,同样受限 | 放请求头,天然跨域 |
| 失效控制 | 删掉即失效(但可被复制) | 删记录立即失效 | 到期前难撤销 |
| 典型体积 | 单条约 4 KB 上限 | 只存一个 ID,很小 | 声明越多越大 |
2. 两条典型链路
Session 方案,状态留在服务端:
浏览器 服务端 Session 存储
|-- POST /login (账密) ------->| |
| |-- 生成 sid,写入 ---------->|
|<-- 200 + Set-Cookie: sid ---| |
|-- GET /order (Cookie: sid)->|-- 按 sid 查会话 ---------->|
|<-- 200 订单数据 ------------| |
Token 方案,状态装进凭证:
浏览器 服务端
|-- POST /login (账密) ------->| 校验账密
|<-- 200 {access_token} ------| 签名后返回,不落库
|-- GET /order |
| Authorization: Bearer ...->| 验签 + 检查 exp / iss / aud
|<-- 200 订单数据 ------------|
关键差别在最后一步:Token 链路里服务端没有查任何存储就确认了身份,所以它天然适合多实例、跨域和移动端。
3. 落地时真正要写的代码
Cookie 的安全属性比内容更重要,值只放随机 ID:
http.SetCookie(w, &http.Cookie{
Name: "sid",
Value: sid, // 128 bit 随机数,不放用户信息
Path: "/",
HttpOnly: true, // 禁止 document.cookie 读取,缓解 XSS 窃取
Secure: true, // 只在 HTTPS 下发送
SameSite: http.SameSiteLaxMode, // 跨站 POST 不携带,缓解 CSRF
MaxAge: 7200,
})
JWT 的结构决定了它"可读不可改":
header.payload.signature
{"alg":"HS256","typ":"JWT"} . {"sub":"1001","exp":1730000000} . HMAC(前两段, 密钥)
payload 只是 Base64URL 编码,任何人都能解开看,所以手机号、身份证号不能放进去; 签名只保证内容没被篡改,不提供保密性,保密要靠 HTTPS。
4. 怎么选
- 单体后台、同域页面:Session + Redis,简单,能随时踢人。
- 前后端分离、多端(Web / App / 小程序)、服务间调用:Token,短效 access token 配长效 refresh token。
- 要求"改密即全端下线":Token 必须补撤销手段,纯 JWT 做不到。
5. 常见追问
Q:JWT 签发后撤不回怎么办? 三招:把有效期压短(如 15 分钟);维护撤销名单(Redis 存 jti,验签后再查一次,等于重新引入状态); 用户维度版本号,改密或登出时自增,旧 token 里的 ver 对不上就拒绝。
Q:Token 放 localStorage 还是 Cookie? localStorage 不自动携带,天然免疫 CSRF,但 XSS 能直接读走; HttpOnly Cookie 挡住 XSS 读取,却要面对 CSRF,得靠 SameSite 加 CSRF token 兜底。没有绝对安全,只有权衡。
Q:分布式 Session 怎么做? 粘性会话(负载均衡把同一用户固定到一台)、会话复制(一致性差)、集中存储(Redis 最常见)。 生产上基本是 Redis,过期时间略大于业务会话时长,并接受"Redis 挂了会掉登录态"这一现实。
Q:Cookie 有数量限制吗? 单条约 4 KB,单个域名下通常几十条,超了浏览器静默丢弃。 表现为"偶发登录失效",排查时容易误判成后端问题。
Q:Session 和 Token 能混用吗? 能。常见做法是 Token 只做认证,权限、在线状态仍存 Redis,用 jti 做黑名单,兼顾无状态与可控性。
小结
Cookie 管"怎么带",Session 管"状态存在服务端",Token 管"凭证自带证明"。 选型只看两个问题:状态放在哪一侧、失效需要多快。 需要秒级踢人就保留服务端状态;需要横向扩展与跨端就用签名凭证,再用短有效期把撤销窗口压小。