OAuth2.0 和 OIDC 中,Session 是如何工作的?

从“门禁卡”到“储物柜”:OAuth2/OIDC 中的 Session 双雄
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。
这样,任何一台服务器都能从 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”为例)
第一次跳转: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 时:
- App B 将用户重定向到授权服务器。
- 授权服务器发现浏览器已经携带了
AUTH_SESSION的 Cookie。 - 授权服务器直接完成授权(无需再次登录),返回授权码给 App B。
- 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。
5.3 安全配置清单
| 配置项 | 授权服务器 Session | 客户端 Session | 说明 |
|---|---|---|---|
| HttpOnly | ✅ 必须 | ✅ 必须 | 防止 XSS 窃取 |
| Secure | ✅ 必须 | ✅ 必须 | 仅 HTTPS 传输 |
| SameSite | Lax 或 Strict |
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”的地图,都会让你走得更稳。
更多推荐


所有评论(0)