4. 会话生命周期管理

SSO 会话并不是“登录成功后一直有效”的静态凭证,而是一条有明确起止的生命周期。企业里绝大多数会话类安全事故,并不是加密算法被攻破,而是生命周期某一阶段的控制点缺失:创建时没有绑定设备与来源、维持时缺少风险感知、续期时无限延长、注销时只清了本地 Cookie 而没动中心会话。理解这条链路上每个阶段“谁在写、谁在读、谁在失效”,比记住某个协议细节更有价值。

一、创建阶段:把身份、设备与上下文绑定在一起

会话创建发生在 IdP 完成认证、向 SP 签发断言或令牌的那一刻。此时最关键的动作是生成一个不可预测的会话标识,并把它与三类信息绑定:主体身份(sub)、客户端上下文(设备指纹、User-Agent、IP 段)、以及认证强度(是否 MFA、认证时间、认证方法)。

常见漏洞有三类。第一是会话固定(Session Fixation):攻击者先获取一个会话 ID,诱导受害者用该 ID 完成登录,登录后服务端未重新生成会话标识,攻击者即可复用同一 ID 进入已认证会话。防御要点是认证成功后必须调用会话重建,使旧 ID 立即失效。第二是断言重放:SAML 断言或 OIDC 授权码缺少一次性校验(如 InResponseTo、nonce、jti),被截获后可在有效期内重复使用。第三是令牌过度授权:创建时把 scope 或角色一次性放大,后续无法收敛。

下面这张图给出会话从创建到注销的完整生命周期,以及每个阶段对应的核心控制点与典型失效点。

SSO 会话生命周期:控制点与失效点 ① 创建 认证成功 → 生成会话 ② 维持 每次请求校验与风险感知 ③ 续期 刷新令牌 / 滑动过期 ④ 注销 单点登出 / 全局失效 安全控制点 • 认证后重建会话 ID • 绑定 sub / 设备 / IP 段 • 记录认证强度与时间 • 断言 nonce / jti 一次性 • 最小 scope 授权 安全控制点 • 每请求校验签名/有效期 • 会话与设备指纹比对 • 异常 IP / 地理跳变告警 • 空闲超时(Idle Timeout) • 并发会话数限制 安全控制点 • 刷新令牌轮换(Rotation) • 绝对超时上限(Absolute) • 续期时重新评估风险 • 敏感操作强制重认证 • 旧刷新令牌立即作废 安全控制点 • 中心会话先失效 • 广播 SLO 到各 SP • 清理本地 Cookie/缓存 • 撤销刷新令牌与访问令牌 • 记录注销审计日志 常见漏洞 • 会话固定未重建 ID • 断言重放 • 令牌 scope 过大 • 会话 ID 可预测 常见漏洞 • 无空闲超时,会话永活 • 不校验设备指纹 • 令牌被窃后无法感知 • 并发会话无上限 常见漏洞 • 刷新令牌不轮换 • 无绝对超时,无限续期 • 续期不重新评估风险 • 旧令牌未作废 常见漏洞 • 只清本地 Cookie • 中心会话仍有效 • SLO 未广播到全部 SP • 令牌未撤销 T0 认证完成 T0~Tn 请求期 Tn 续期点 Tend 注销

二、维持阶段:从“一次认证”到“持续信任”

会话建立后,真正的安全博弈发生在维持阶段。核心原则是:信任不是一次性的,而是每次请求都要重新确认的。服务端在每次请求中至少要校验四件事:令牌签名是否有效、是否在有效期内、会话是否仍处于活跃状态、当前请求上下文是否与创建时绑定的上下文一致。

空闲超时(Idle Timeout)与绝对超时(Absolute Timeout)是两个必须同时存在的参数。空闲超时指会话在无操作一段时间后失效,例如 30 分钟;绝对超时指无论是否活跃,会话从创建起最多存活多久,例如 8 小时或 12 小时。只设空闲超时,攻击者可以持续发请求“保活”;只设绝对超时,用户离开工位后会话仍可能被利用。两者叠加才能覆盖“人走了”和“人一直在但设备被控”两种场景。

设备指纹与 IP 段比对是维持阶段最有效的异常发现手段。当同一会话突然从不同 ASN、不同国家或不同设备指纹发起请求时,应触发风险评分。评分超过阈值时,可采取降级措施:要求重新 MFA、限制敏感操作、或直接终止会话。这里要注意,IP 会因移动网络切换而合理变化,因此不宜把 IP 完全固定,而应使用“IP 段 + 地理速度”组合判断,例如两次请求间隔 5 分钟却跨越 2000 公里,即判定为不可能旅行。

三、续期阶段:刷新令牌的轮换与上限

现代 SSO 普遍采用“短生命周期访问令牌 + 长生命周期刷新令牌”的结构。访问令牌通常 5~15 分钟,刷新令牌 7~30 天。续期阶段最大的风险是刷新令牌被窃取后长期复用。防御的核心是刷新令牌轮换:每次使用刷新令牌换取新访问令牌时,同时签发一个新的刷新令牌,并立即作废旧的刷新令牌。

轮换必须配合“重放检测”。如果服务端收到一个已经被作废的刷新令牌,说明该令牌可能已被攻击者复制,此时应立刻撤销该会话对应的整个令牌族(Token Family),强制用户重新认证。此外,续期不能无限进行,必须设置绝对超时上限。例如刷新令牌本身最长 30 天,且每次续期时重新评估设备与风险,风险升高则拒绝续期。

续期请求示例(OIDC Refresh Token Grant)
POST /token
grant_type=refresh_token
refresh_token=rt_9f3a...c21
client_id=corp-portal

服务端处理逻辑:
1. 校验 rt_9f3a...c21 是否在有效刷新令牌集合中
2. 若不在(已被轮换作废)→ 判定重放,撤销整个 Token Family
3. 若在 → 签发新 access_token(10min)与新 refresh_token
4. 将 rt_9f3a...c21 标记为已使用并作废
5. 检查会话创建时间是否超过绝对超时(如 30 天)→ 超过则拒绝续期

四、注销阶段:单点登出必须“全局生效”

注销是最容易被低估的阶段。很多系统只做了本地 Cookie 清除,用户以为已退出,但 IdP 中心会话仍然有效,攻击者拿到该会话即可免密进入其他已登录的 SP。完整的注销应包含三个动作:第一,使 IdP 中心会话失效;第二,通过 SLO(Single Logout)协议向所有已建立会话的 SP 广播注销通知;第三,撤销该会话关联的访问令牌与刷新令牌。

SLO 的工程难点在于“广播的可靠性”。如果某个 SP 暂时不可达,注销通知可能丢失,导致该 SP 仍保留本地会话。实践中通常采用“中心会话失效 + SP 短时校验”的组合:SP 在每次请求时向 IdP 校验会话状态(或使用短生命周期令牌),即使 SLO 通知丢失,SP 也会在令牌过期后自然失效。对于高敏感系统,可进一步要求 SP 在关键操作前主动调用 IdP 的会话校验接口。

常见误区:把“关闭浏览器”等同于“注销会话”。关闭浏览器只清除本地 Cookie,中心会话和刷新令牌仍然有效。企业应在培训中明确区分“关闭标签页”“退出当前应用”“全局注销”三种操作的实际效果。

五、各阶段控制点速查

阶段 核心控制点 关键参数示例 典型漏洞
创建 认证后重建会话 ID、绑定设备与来源、断言一次性校验 会话 ID 长度 ≥128 bit;nonce 有效期 ≤5 min 会话固定、断言重放、scope 过大
维持 每请求校验、空闲超时、设备指纹比对、并发限制 空闲超时 30 min;并发会话 ≤3 会话永活、令牌被窃无感知
续期 刷新令牌轮换、重放检测、绝对超时、风险重评估 访问令牌 10 min;刷新令牌 30 天;绝对超时 12 h 刷新令牌不轮换、无限续期
注销 中心会话失效、SLO 广播、令牌撤销、审计记录 SLO 通知重试 3 次;令牌撤销延迟 ≤5 s 只清本地 Cookie、SLO 未广播

把四个阶段串起来看,会话安全本质上是一道“时间与上下文”的约束题:创建时绑定得越紧,维持时校验得越勤,续期时收敛得越果断,注销时清理得越彻底,攻击者能利用的窗口就越小。企业落地时不必一次追求全部控制点,但应优先补齐三个最容易被利用的缺口——认证后重建会话 ID、刷新令牌轮换、以及中心会话先失效的全局注销。