会话与令牌:过期、撤销与一次没退出的登录

共享电脑上的一次登录没有退出,四个小时里谁都能接着用。他用 344 个账号、619 个活跃会话与 310 KB 的会话表,换来三个数字:绝对过期 30 天、空闲过期 14 天、撤销延迟 0 秒,以及一次必须记住的登录教训。

会话的安全感不来自令牌有多长,而来自你能否在下一秒把它作废。

一、一次没有退出的登录

2026 年 8 月的一个下午,他在客户的会议室里用共享电脑演示任务板。演示结束,他合上笔记本就走,浏览器里的登录状态还留着。四个小时后,下一位使用者打开同一个标签页,直接看见了这个账号的全部项目、成员列表和导出按钮。

以下情境为教学假设,人物、引语和数字不代表经核实的真实案例。

他当天傍晚才发现:审计记录里多了一次不需要重新输入密码的导出。时间线很清楚,十四点零五分演示结束,十八点多那次导出发生,中间四个小时里,任何人都可以接着用这个已经登录的会话。

那天晚上他做的第一件事不是换框架,而是给会话装一个随时能关掉的开关:会话存服务端,登出时删掉那一行,删完立刻失效。代价是一张表和每次请求一次主键查询,收益是撤销延迟从「等令牌过期」变成零。

他把这个开关写进了三条规则:任何设备都能单独踢下线、改密码后踢掉全部设备、权限变更后让旧会话立刻重新校验。三条规则加起来不到四十行代码,却把「人已经走了,权限还在」这类事故挡在门外。

二、会话表与无状态令牌的取舍

他先把两种做法摆在一张表上,而不是先选库。表里的「撤销延迟」一列是决定性的一列,因为事故发生时,人能做的只有撤销。

维度服务端会话表无状态 JWT
撤销延迟0,删行即失效最长 15 分钟,等令牌过期
每次请求成本一次主键查询一次本地签名校验
登出全设备删该用户的全部会话行需要额外的黑名单或版本号
服务端容量619 个会话约 310 KB不占服务端存储
数据库故障时全员暂时无法校验校验仍可在本地完成
适合的场景单体应用、需要即时撤销跨服务调用、极短时效

他选了会话表,理由只有一个:这个产品里最贵的动作是「把人赶出去」。 客户离职、设备丢失、共享电脑忘记退出,这三件事都要求撤销在下一秒生效;等十五分钟的令牌过期,在这三个场景里都等于没有撤销。

JWT 不是错的,错的是把它当会话用。 无状态令牌适合服务之间的短时调用,最长十五分钟的撤销延迟在那种场景里可以接受;一旦拿它承载浏览器登录态,你就必须自己补一套黑名单,最后又回到服务端存储。

混合方案他没有采用。 同时维护会话表和令牌黑名单,意味着两套过期逻辑、两处撤销入口;一个人的产品里,多一套状态就是多一个会忘记清理的角落。

过期与撤销是两件事,不能互相替代。 过期解决「令牌活得太久」,撤销解决「令牌不该再活」;只有过期没有撤销,事故期间你只能看着它继续有效。

会话行里要留下能解释的字段。 创建时间、最后活动时间、设备摘要、权限版本,四个字段足够在复盘时说清「谁在什么时候从哪里进来」。

会话 ID 用 32 字节随机数,不用自增主键。 随机数让「猜下一个会话」这件事没有着力点;自增主键省不了多少空间,却把枚举变成了一个可以写脚本的动作。

会话表只存哈希,不存原始 ID。 数据库被读走时,攻击者拿到的是一串哈希,无法直接拿来冒充;校验时对请求里的 ID 做一次哈希再比对,成本是一次内存里的运算。

三、三十天、十四天与零秒

三个数字定下之后,会话的行为就不再靠感觉。他给每个数字都写了「为什么是这个值」和「失败时会发生什么」。

参数取值为什么设置失误的后果
绝对过期30 天超过一个月不登录的设备,多半已经不用了长期不用的设备一直持有有效会话
空闲过期14 天两周没有操作,人大概率已经离开这个场景共享电脑上的会话可以无限续命
撤销延迟0 秒删行即失效,不等任何缓存踢下线要等令牌过期,事故窗口被拉长

绝对过期从登录那一刻算,不随活动续期。 这条规则让「一直开着标签页」也无法把会话续到一年;到期就重新登录,成本是三十天一次,换来的是会话不会永久存在。

空闲过期从最后一次请求算,十四天。 它和绝对过期是两条独立的线,先到先失效;两条线都设,是因为它们防的不是同一件事:一条防「设备被遗忘」,一条防「人已离开但页面还开着」。

撤销延迟零秒靠的是每次请求都查库。 他试过在内存里缓存会话,登录页的响应快了一点,但踢下线要等缓存过期;这点收益不值得,缓存被删掉了。

619 个活跃会话不是拍脑袋的数。 344 个账号,平均每人 1.8 台设备,乘出来 619.2,取整 619;每个会话约 0.5 KB,整张表 310 KB 左右。

1.8 台设备是平均值,不是上限。 有人在手机、平板和两台电脑上同时登录,单个账号的会话数会明显高于平均值;容量按平均值算,风控要按最大值想。

310 KB 说明容量不是问题,索引才是。 会话表按 user_id 建索引,登出全设备就是一条按用户删除的语句;没有这个索引,一次全设备登出会扫全表,人越多越慢。

会话表也要有清理任务。 每天删一次已经过期的行,表不会无限增长;清理失败不影响登录,但会在几周后表现为查询变慢。

会话数量要能被看见。 他在账号设置里放了一个「已登录设备」列表,显示设备、最近活动时间和当前会话标记;用户能自己踢掉不认识的设备,比等他发现日志要快得多。

四、四个小时与十六个窗口

把这次事故的账算一遍,就能看出「等过期」和「即时撤销」差在哪里。

复算:
活跃会话 = 344 账号 × 1.8 设备 = 619.2 → 619 个
存储占用 = 619 × 0.5 KB = 309.5 KB ≈ 310 KB
每账号平均会话 = 619 ÷ 344 = 1.8 个
暴露时长 = 4 小时 = 240 分钟
无状态 JWT(撤销延迟上限 15 分钟):240 ÷ 15 = 16 个窗口
服务端会话(撤销延迟 0 秒):发现即失效,窗口 = 0

十六个窗口的意思是,在最坏情况下有十六次机会让旧令牌继续通过校验。 这不是说 JWT 一定被利用,而是说撤销动作在这四个小时里没有任何一次真正生效;服务端会话把这段窗口压成一次请求的时间。

窗口数量只是上界,不是命中次数。 旧令牌要在这十六个窗口里被使用才会产生实际影响;但安全设计不能假设「没人会用」,只能假设「一定会被用」。

四个小时的暴露不全是技术问题。 共享电脑上的登录没有退出,首先是使用习惯;但如果系统支持「查看已登录设备并一键踢掉」,习惯的代价可以从四小时降到一次点击。

会话表让「改密码」有了明确含义。 改密码时删掉该用户全部会话,旧设备下一次请求就被弹回登录页;如果只改密码不删会话,用户会以为安全了,实际旧设备还能用。

权限变更也要碰会话。 把成员从管理员降为普通成员后,旧会话里的角色缓存必须失效;他的做法是会话行里存一个权限版本号,权限一变就递增,请求时版本不符即重新加载。

会话过期不等于数据过期。 会话删掉只是让人重新登录,已经导出的数据不会因此回收;这两件事的边界要在隐私说明里分别写清楚。

空闲过期的实现要防「后台轮询续命」。 如果前端定时拉取通知,空闲过期永远不会触发;他的做法是只有用户主动操作才算活动,轮询请求不刷新最后活动时间。

三十天绝对过期快到时要提前提示。 临近到期时在界面顶部显示一次「登录即将过期」,避免用户在写一半的任务描述时被弹回登录页;提示本身不续期,只是让人有准备。

五、行动清单与复算验收

按顺序做,会话行为就会从「默认配置」变成「写下来的规则」。

  • 统计当前活跃会话数与每账号平均设备数,算出会话表占用。
  • 给会话表加 user_id 索引,验证一次全设备登出所需的查询计划。
  • 设定绝对过期 30 天与空闲过期 14 天,并确认两者独立生效。
  • 把登出实现为删行,验证删除后旧会话的下一次请求被拒绝。
  • 在账号设置里加「已登录设备」列表与单设备踢下线入口。
  • 改密码与权限变更时,强制失效该用户的全部旧会话。
  • 确认前端轮询不会刷新最后活动时间,避免空闲过期失效。
  • 用一次测试账号走完「登录、换设备、踢下线、改密码」四条路径并记录耗时。

验收标准:你能在三十秒内让任意一个会话失效,并能说清绝对过期与空闲过期各自防的是什么;做不到,会话就还处在「等它自己过期」的状态。

前四条是机制,后四条是让人看得见机制。如果只有半天,先做第一条和第四条;没有会话清单,后面的设备管理和过期策略都无从验证。

清单不要一次全做。第一周只做统计与索引,第二周加设备列表,第三周才改过期参数;一次改太多,出问题时分不清是哪一条引起的。

使用边界与实操验收

会话表不是唯一答案。 它适合单体应用和需要即时撤销的场景;如果产品已经拆成多个服务,会话校验可能要走一次内部调用,那时再评估短时效令牌加撤销名单。

三个数字是教学取值,不是行业标准。 30 天与 14 天取自本组基线,换一个产品、换一类用户,取值会不同;重要的是两个数字都写下来,并且能说出失败时的后果。

零秒撤销依赖每次请求查库。 数据库不可用时,所有人都会被挡在门外;这是有意的取舍,因为「暂时进不来」比「该出去的人出不去」更容易解释,也更容易恢复。

设备列表会暴露一部分隐私。 列表里只显示设备类型、浏览器和最近活动时间,不显示精确位置;显示得越细,越容易变成另一种信息泄露。

本文只讨论会话与令牌的生命周期。 数字全部是教学假设,不构成对任何框架、库或云服务的推荐;具体实现以你所选技术栈的官方文档为准。

关键参考与核验范围

  • OWASP Session Management Cheat Sheet :用于核对会话 ID 的生成、过期与登出后的处理要求。
  • NIST SP 800-63B :用于核对认证器与会话生命周期中与保证等级相关的要求。
  • OWASP ASVS :用于核对会话管理相关的验收条目,本文不逐条对照。
  • OWASP Top Ten :用于说明身份认证与会话失效这一类风险的常见形态。

以上链接于 2026-10-26 实测可公开访问;未核验版本、条款编号与具体建议。核验日期:2026-10-26。

边界句。 本文只讨论一人产品的会话存储、过期与撤销,不讨论单点登录、多因素认证的产品选型与合规审计。

系列导航

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「Indie」更多文章

  1. 开源项目验收:十项能力、四维评分与三种不该开源的项目
  2. 治理、fork 与退出:17 位贡献者、82% 的提交与一次改协议的代价
  3. 双许可与企业版:九家询价、两家成交与 4,800 美元