返回知识库

数据与服务 · 账号与安全

会话Session

会话是服务端存的一条记录:登录建记录并把 id 写进 Cookie,请求按 id 查记录恢复身份,退出删的是服务端记录——不只是清浏览器 Cookie。

登录建记录、请求查身份、退出删记录

会话不是浏览器自己记住的,而是服务端存了一条记录。先在这一台登录、发请求、推进时间、退出,亲眼看到服务端记录的出现、过期和消失,再读后面的规则命名。

登录在服务端建一条会话记录(id + 身份 + 过期),浏览器只拿到 id(通常写在 Cookie 里)。 每个私有请求靠 id 反查记录恢复身份;退出删的是服务端记录,不只是清浏览器。

服务端会话存储无记录

(空)没有会话记录;私有请求会返回 401。

服务端时钟 T+0m

还没有发过私有请求;点「发起私有请求」看服务端按 id 查记录的结果。

登录时换 id
空闲续期
模拟会话固化

原因:服务端还没有会话记录,浏览器也没有 Cookie。下一步:点「登录」在服务端建记录、把 id 写进 Cookie。对照:登录后看「服务端会话存储」出现一行,「浏览器 Cookie」拿到同一个 id。

提示:主操作「登录」是唯一的红色按钮;其余按 Tab 顺序可达。重点试三条对照——推进时间到过期再请求、退出后用旧 id 再请求、开关「登录时换 id」对比固化结果。

存储台暴露的五条服务端规则

面板已经把每条规则演给你看了,这里把它们命名清楚,并补上无法直接操作的部分。

  • 会话 = 服务端记录,不是浏览器自带的状态:登录在服务端建 { id, 身份, 过期 },浏览器只收到 id(通常写在 Set-Cookie: sid=… 里)。秘密留在服务端,浏览器一侧不存身份细节。
  • 请求靠 id 反查记录恢复身份:每个私有请求带 Cookie: sid=…,服务端在存储里查这个 id——查到且未过期就恢复身份;查不到、过期或不匹配都返回 401,要求重新登录。
  • 过期是服务端判定的状态expiresAt 到点即过期,即便浏览器 Cookie 还在也一样被拒;空闲续期(滑动)在每次请求时把过期推后,绝对过期不动,到达上限必须重新登录。
  • 退出 = 删服务端记录:登出要撤销服务端记录,并清掉浏览器 Cookie;只清浏览器不算登出——记录残留时,被偷来的 id 在过期前仍能使用。
  • 会话固化靠「登录时换 id」防御:登录时总是重新生成新 id,丢弃任何预置值;攻击者预先植入的 id 不会成为登录后的会话 id,固化攻击失败。
  • 承载 Cookie 的安全属性交给 cookie 术语Secure / HttpOnly / SameSite 决定浏览器是否自动携带、脚本能否读取——这些在 cookie 卡片判定,这里只关心服务端记录。

什么时候用服务端会话,什么时候换 token

从「谁来记状态、能不能即时撤销」出发,而不是默认都用会话。

  • 用服务端会话:Web 端登录态、需要随时主动撤销(踢人下线、登出立即生效)、记录可枚举与审计的场景。状态在服务端,撤销就是删一条记录。
  • 换 JWT / 无状态 token:跨设备或跨服务复用凭据、不想要服务端存储、能接受「撤销靠短时效 + 黑名单」时,签名 token 更合适。它不在服务端留记录,过期前服务端无法单条作废。
  • 混用:浏览器同站请求用 Cookie + 服务端会话;开放 API 用 Authorization: Bearer … token。两套凭据各自管过期与撤销。
  • 不要做的:把密码、完整身份信息塞进 Cookie 或 token;用可推测的 id;登出只清浏览器不撤销服务端记录。

从登录到登出:服务端会话最短路径

只走这几步,每步都改变服务端可验证的状态。

  1. 登录验证通过后,生成随机不可预测的 opaque id,在存储(内存 / 数据库 / Redis)里写入 { id → 身份, 创建, 过期 };始终重新生成 id,不复用请求里带来的任何 id。
  2. 把 id 写进 Set-Cookie: sid=…; Secure; HttpOnly; SameSite=Lax; Max-Age=…;后续请求浏览器自动带,服务端按 id 查记录恢复身份,不在前端读 sid 再回传。
  3. 每个请求校验 id 存在、未过期、未撤销;敏感操作(改密码、转账)另要求再验证一次;需要时用空闲续期滑动过期,但仍设绝对上限。
  4. 登出时删除服务端记录,并用同名、同 Domain、同 Path 的 Max-Age=0 清浏览器 Cookie;检测到异常(泄漏、改密码)时按用户撤销其全部会话。

同一目标「登出后立刻不可访问」:删服务端记录,还是只清浏览器

只改一处——退出时删什么——结果差很多。这是会话生命周期里最该记住的一条。

正例:退出调撤销接口,删除服务端会话记录DELETE /sessions/{id} → 存储 remove(id);Set-Cookie: sid=; Max-Age=0

记录从服务端消失;即便刚才的 sid 被偷过、浏览器还残留 Cookie,再请求也查不到记录,返回 401。这是真正生效的登出。

反例:前端只清浏览器 Cookie,没调撤销document.cookie = "sid=; Max-Age=0"(服务端记录原样保留)

服务端记录仍在存储里且未过期;如果 sid 曾被偷(日志、XSS、中间人),攻击者拿着它继续请求,依然 200。登出形同虚设。

快速自测

你的会话存在 Redis,用户点了退出,但前端只清了浏览器 Cookie、没调撤销接口。接下来到过期前会发生什么?

继续查证

术语的技术定义和行为以这些一手或权威资料为准。

下一步学

和本知识点经常一起出现的概念。