在这里插入图片描述

1. 引言:一张门禁卡,两个储物柜

想象你去一家大型连锁健身房。你在前台办了会员卡,前台工作人员核验你的身份后,给了你一张门禁卡(授权服务器 Session)。这张卡能让你进入任何一家分店。但当你走进具体某家分店时,你会领到一把临时储物柜钥匙(客户端 Session),这把钥匙只能打开你在这家店的柜子。门禁卡是通用的,储物柜钥匙是专用的,它们一起工作,让你既能跨店通行,又能在每家店安全存放私人物品。

在 OAuth2/OIDC 体系中,授权服务器 Session客户端 Session 扮演的正是这样的角色。前者是用户与认证中心的“统一门禁”,后者是用户与具体业务应用的“独立储物柜”。本文将从最基础的概念讲起,深入剖析这两类 Session 如何协同工作,实现单点登录(SSO),并解答一个核心问题:为什么有了 Token,还需要 Session?


2. 基础层:Session 与 Token 的前世今生

在理解 OAuth2/OIDC 的 Session 设计之前,我们先回顾一下 Web 应用最朴素的会话管理方式。这能帮助我们理解“为什么需要两类 Session”这个问题的历史根源。

2.1 上古时代:Session 与 Cookie 的“绑定”

早期 Web 应用很简单:用户登录后,服务器在内存中创建一个 Session 对象,生成一个随机的 Session ID,通过 Set-Cookie 返回给浏览器。浏览器保存这个 Cookie,后续请求自动携带。服务器根据 Session ID 找到对应的 Session 数据。

这种方式简单直接,但有一个致命问题:有状态。当应用从单机扩展到集群时,用户的请求可能落在不同服务器上,Session 数据不共享,用户就会被“踢下线”。

2.2 近代方案:集中式 Session 存储

为了解决集群共享问题,人们把 Session 从应用服务器内存中抽出来,放到一个集中存储中——最常见的就是 Redis

用户

负载均衡

应用服务器1

应用服务器2

Redis

这样,任何一台服务器都能从 Redis 中读取 Session,实现了无状态的应用服务器 + 有状态的 Session 存储。这个模式至今仍在大量系统中使用,结构简单,运行高效。

2.3 微服务时代:自包含 Token 的崛起

微服务架构中,一个请求可能穿越多个服务。如果每个服务都要去 Redis 查询 Session,会带来额外的网络开销和延迟。于是,自包含 Token(如 JWT) 出现了。

Token 本身携带用户信息(如用户 ID、角色),服务端收到后直接解码验证,无需查询共享存储。这就是 无状态认证

2.4 核心关系:Session 是“状态”,Token 是“凭证”

概念 本质 存储位置 生命周期控制
Session 会话状态(用户与系统的“连接”) 服务端(内存/Redis) 服务端可控,可主动销毁
Token 凭证(证明“你是谁”) 客户端(Cookie/Storage) 由过期时间控制,难以主动撤销

理解了这个区别,我们就进入了 OAuth2/OIDC 的世界——Session 和 Token 不是替代关系,而是分工协作的关系


3. 协议层:OAuth2 授权码流程中的“两次跳转”

OAuth2 最常用的模式是 授权码模式(Authorization Code Flow),它包含两次关键的浏览器跳转。正是这两次跳转,引出了两类 Session 的诞生。

3.1 四大角色

  • Resource Owner:终端用户(你)
  • Client:第三方应用(想用你的身份登录的 App)
  • Authorization Server:授权服务器(负责认证和颁发令牌)
  • Resource Server:资源服务器(存储你的数据)

3.2 核心流程(以“用 Google 登录某 App”为例)

授权服务器(Google) 第三方App 用户浏览器 授权服务器(Google) 第三方App 用户浏览器 点击“用Google登录” 302重定向到Google登录页 访问Google登录页 展示登录表单 输入用户名密码 创建授权服务器Session 302重定向回App,携带授权码(code) 访问回调地址,带code 后端用code换token 返回access_token + id_token 创建客户端Session 登录成功

第一次跳转:App 把用户浏览器重定向到 Google 的登录页。这一步让 Google 直接和用户交互,App 全程看不到密码。

第二次跳转:用户登录成功后,Google 把浏览器重定向回 App 预设的地址,并在 URL 上附带一个授权码(code)。注意,这里返回的是授权码,不是 token。为什么?因为 token 是敏感的,如果直接返回给浏览器,可能被截获。授权码是一次性的,且只能由 App 的后端去换 token,安全性更高。


4. 机制层:两类 Session 的诞生与协作

在 OAuth2/OIDC 流程中,实际上存在两个独立的 Session,它们各自承担不同的职责。

4.1 授权服务器 Session(IdP Session)

定义:用户与授权服务器之间的认证会话,通常以 AUTH_SESSION 为名,存储在授权服务器的域下(如 auth.example.com)。

作用

  • 记录用户“已经登录过授权服务器”这一事实。
  • 实现 单点登录(SSO):当用户访问第二个应用时,重定向到授权服务器,服务器发现已有 AUTH_SESSION,直接跳过登录页,静默完成授权。

典型配置

Set-Cookie: AUTH_SESSION=abc123; Domain=auth.example.com; HttpOnly; Secure; SameSite=Lax

4.2 客户端 Session(RP Session)

定义:客户端应用与用户浏览器之间的会话,存储在客户端的域下(如 app.example.com)。

作用

  • 管理用户在具体业务应用中的登录态。
  • 存储用户身份信息(通常从 ID Token 中获取)和 Token 的引用(如 Refresh Token 的引用,而不是 Token 本身)。
  • 避免每次请求都携带 Access Token 到服务端验证,减少开销。

典型配置

Set-Cookie: APP_SESSION=xyz789; Domain=app.example.com; HttpOnly; Secure; SameSite=Lax

4.3 为什么需要两类 Session?

维度 授权服务器 Session 客户端 Session
存储位置 授权服务器域(如 auth.com) 客户端域(如 app.com)
生命周期 由授权服务器控制(如 30 分钟无操作过期) 可独立设置,通常短于或等于授权服务器 Session
主要作用 集中认证,实现 SSO 承载业务上下文,管理 Token 引用
安全要求 极高,必须 HttpOnly、Secure、SameSite 高,同样需安全配置

核心原因职责分离

  • 授权服务器负责“你是谁”的认证,它的 Session 是跨应用的。
  • 客户端负责“你在本应用能做什么”的业务状态,它的 Session 是应用私有的。

如果只用授权服务器 Session,每个业务应用每次请求都要去授权服务器验证,性能差;如果只用客户端 Session,那就无法实现跨应用的 SSO。

4.4 SSO 的实现原理

当用户第一次登录 App A 时,授权服务器创建 AUTH_SESSION。当用户访问 App B 时:

  1. App B 将用户重定向到授权服务器。
  2. 授权服务器发现浏览器已经携带了 AUTH_SESSION 的 Cookie。
  3. 授权服务器直接完成授权(无需再次登录),返回授权码给 App B。
  4. App B 用授权码换取 Token,并创建自己的客户端 Session。

这就是 “无感单点登录” 的底层原理。


5. 工程层:Session 的生命周期与安全实践

5.1 生命周期管理

  • 授权服务器 Session:通常设置为 30 分钟无操作过期。用户长时间不活动后,需要重新登录。这是安全与体验的平衡。
  • 客户端 Session:可以设置得短一些(如 15 分钟),通过 Refresh Token 机制自动续期,确保用户在操作过程中不会突然掉线。

5.2 Token 与 Session 的配合

  • Access Token:短期有效(如 15 分钟),放在客户端 Session 中,每次请求由后端携带去调用资源服务器。
  • Refresh Token:长期有效(如 7 天),放在 HttpOnly Cookie 中(或后端存储),用于在 Access Token 过期时获取新的 Access Token。

有效

失效

有效

无效

用户

客户端应用

检查客户端Session

返回业务数据

检查Refresh Token

向授权服务器换取新Access Token

更新客户端Session

重定向到授权服务器

5.3 安全配置清单

配置项 授权服务器 Session 客户端 Session 说明
HttpOnly ✅ 必须 ✅ 必须 防止 XSS 窃取
Secure ✅ 必须 ✅ 必须 仅 HTTPS 传输
SameSite LaxStrict Lax 防御 CSRF
Domain 父域或精确域 精确域 控制作用域
过期时间 30 分钟无操作 15 分钟或随 Refresh Token 平衡安全与体验

5.4 分布式环境下的 Session 共享

授权服务器和客户端都可能部署多节点。Session 需要集中存储:

  • 授权服务器 Session:存储在 Redis 中,所有授权服务器节点共享。
  • 客户端 Session:同样可存储在 Redis,或使用 Spring Session 等框架自动管理。

6. 问题层:常见误区与澄清

6.1 误区一:ID Token 可以直接替代 Session

正解:ID Token 是 身份断言,用于证明“用户是谁”,通常是一次性使用的。客户端仍需维护自己的 Session 来管理业务上下文,否则每次请求都要验证 ID Token,增加开销。

6.2 误区二:授权服务器 Session 与客户端 Session 生命周期天然一致

正解:两者完全独立。用户可能在授权服务器上已经登出,但客户端 Session 仍然有效(直到过期);也可能授权服务器 Session 有效,但客户端 Session 因 Token 过期而失效。需要显式同步(如登出时通知各客户端)。

6.3 误区三:有了 Refresh Token,客户端就不需要 Session

正解:Refresh Token 用于获取新的 Access Token,而客户端 Session 用于存储用户身份和业务上下文。两者是不同层面的概念。

6.4 误区四:OAuth2 就是登录

正解:OAuth2 是 授权协议,解决的是“第三方应用能否访问我的资源”。OIDC 在 OAuth2 之上增加了身份认证层,才是真正意义上的“登录”。


7. 总结:一张图看懂两类 Session 的协作

层级 组件 职责 存储 生命周期
认证层 授权服务器 Session 集中认证,实现 SSO 授权服务器域 Cookie + Redis 30 分钟无操作
授权层 Access Token API 调用凭证 客户端 Session(或内存) 15 分钟
续期层 Refresh Token 获取新 Access Token HttpOnly Cookie 或后端存储 7 天
应用层 客户端 Session 业务上下文、用户信息 客户端域 Cookie + Redis 15 分钟(可续期)

最终结论

  • 授权服务器 Session 是 SSO 的基石,它让用户只需登录一次,就能访问多个应用。
  • 客户端 Session 是业务应用独立运行的基础,它让每个应用有自己的登录态和上下文。
  • Token 与 Session 是配合关系,不是替代关系:Session 管理“状态”,Token 充当“凭证”。

理解这两类 Session 的分工与协作,是构建高安全、高可用的 SSO 架构的关键。无论你是在设计企业级身份平台,还是在为自己的应用接入 OAuth2/OIDC,这张“双 Session”的地图,都会让你走得更稳。

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐