Session、JWT、OAuth 2.0 与 OIDC
本文负责登录状态、令牌格式与委托授权协议。Session 保存会话,JWT 表达声明。OAuth 2.0 用于授权,OIDC 提供身份协议。
1. 面试核心
先记住这几条,再读正文- Session 状态。 Session 通过随机 ID 关联服务端状态,撤销需使该状态失效。
- JWT 验签与可读性。 签名型 JWT 可离线验签,payload 仍可被持有者读取。卡 · JWT
- 刷新与撤销。 Refresh Token 撤销阻断后续刷新,已签发令牌另需失效机制。
- 授权与登录。 OAuth 2.0 授权访问资源,OIDC 的 ID Token 面向登录客户端。
- 授权流程绑定。 PKCE 绑定授权码兑换,state 关联回调,nonce 绑定认证请求。卡 · PKCE、state 与 nonce
2. Session
登录后,服务端创建会话并返回随机 Session ID。浏览器通过 Cookie 携带该 ID。服务端读取会话状态并执行授权。
多实例可共享会话存储。粘性路由能保留单机状态,但故障恢复仍需另行设计。
Cookie 设置 Secure、HttpOnly 和合适的 SameSite。浏览器请求防护见 XSS 与 CSRF。
2.1 会话固定与失效
登录成功和权限提升后,应更换 Session ID。旧 ID 随之失效,避免攻击者预先固定会话标识。
服务端同时设置空闲超时与绝对有效期。登出要使服务端会话失效,并清除客户端 Cookie。分布式缓存的撤销传播需要满足业务时限。
3. JWT
JWT 可用 JWS 签名,也可用 JWE 加密。本文主要讨论三段式 JWS。签名保护完整性,payload 采用可解码的编码。
资源服务应校验以下字段与约束:
- 算法来自服务端允许列表,签名验证通过。
iss属于受信发行者。aud包含当前资源服务。exp、nbf满足时间要求与允许偏差。- token 类型与 scope 符合当前接口要求。
API 使用为自身签发的 Access Token。ID Token 面向登录客户端,二者需分别验证。签名密钥管理见 密钥轮换。
4. JWT 撤销
离线验签的资源服务看不到实时撤销状态。短期 Access Token 将风险窗口限制在剩余有效期内。
需要立即封禁时,可查询撤销表或会话版本。另一种选择是不透明 token 加 introspection。查询状态会引入延迟与服务依赖。
撤销 Refresh Token 只阻断后续刷新。已签发 Access Token 仍需等待到期或实时撤销。
5. OAuth 2.0
OAuth 包含用户、客户端、授权服务器与资源服务器。用户授权客户端,客户端取得 Access Token 后调用 API。
RFC 9700 要求公共客户端的授权码流程使用 PKCE。机密客户端也推荐使用 PKCE。静态 client secret 在浏览器和原生应用中无法可靠保密。
授权码流程把用户交互和令牌兑换分开:
- 客户端发起授权请求,携带 PKCE challenge。
- 授权服务器完成交互,并返回短期授权码。
- 客户端携带 verifier 到 token endpoint 兑换。
- 授权服务器验证绑定关系,再签发令牌。
重定向 URI 应与登记值精确匹配。原生应用的 localhost 端口有规范例外。密码授权已被 RFC 9700 禁止使用。
5.1 PKCE、state 与 nonce
PKCE 使用每次生成的随机 verifier。S256 方法发送其 SHA-256 challenge。兑换方必须提交匹配的 verifier。
state 绑定本地会话与授权回调。随机值需在回调时比对并一次性消费。
OIDC 的 nonce 绑定认证请求与 ID Token。请求携带 nonce 后,客户端必须核对返回值。nonce 也应关联本次会话并防止重放。
三者保护的绑定关系不同。PKCE 约束授权码兑换,state 关联回调。nonce 将身份结果绑定到发起的认证请求。
6. OIDC
OIDC 在 OAuth 2.0 上增加 ID Token 和 UserInfo。ID Token 的 audience 是登录客户端。稳定用户标识使用 iss + sub。
客户端按使用的流程验证签名、issuer、audience 与期限。请求携带 nonce 时,还需核对该 nonce。auth_time 在请求 max_age 等条件下必需。
邮箱和展示名会变化,应用宜使用稳定主体标识。API 则独立验证 Access Token。
7. Refresh Token
Refresh Token 只交给授权服务器。公共客户端需使用发送方约束或轮换机制。平台安全存储可缩小凭据暴露面。
轮换在刷新成功后签发新 token,并使旧 token 失效。服务端保留所属令牌家族关系。发现旧令牌重用后,撤销该家族的活动刷新令牌。
并发刷新也会触发旧令牌重用。客户端应合并刷新请求。服务端需明确重试语义,避免无界重放宽限。
8. 方案选择
浏览器到 BFF 可使用 Session Cookie。BFF 在服务端保存 OAuth token,再调用资源 API。
方案选择取决于撤销时限与离线验证需求。还需比较客户端存储能力和跨域边界。短期令牌、会话存储与身份协议可以共同使用。
9. 常见问题
9.1 浏览器令牌存储
Local Storage 中的 token 会暴露给成功执行的 XSS。HttpOnly Cookie 可限制脚本读取。Cookie 自动携带时,还需防护 CSRF。
9.2 state 与 nonce 的绑定对象
state 关联回调与本地会话。nonce 关联 ID Token 与认证请求。具体流程见 PKCE、state 与 nonce。
10 · 面试题卡片
10.1 为什么使用 JWT,如何实现撤销和安全刷新?
出现公司:字节跳动
考察重点:离线验签、撤销窗口与刷新轮换。
相关内容:JWT、JWT 撤销、Refresh Token。
参考回答
签名型 JWT 支持资源服务离线验证声明。
服务端仍需校验算法、发行者、受众和有效期。
短期 Access Token 限制泄漏窗口。Refresh Token 轮换检测旧令牌重用。紧急撤权还需查询撤销状态或权限版本。撤销刷新令牌本身不会使已有 Access Token 立即失效。
10.2 PKCE、state 与 nonce 分别保护什么?
出现公司:暂无已核验的公开来源(本站自测)
考察重点:授权码兑换、回调关联与认证结果绑定。
相关内容:PKCE、state 与 nonce。
参考回答
PKCE 绑定授权码与 verifier,state 关联授权回调。
nonce 把 ID Token 绑定到本次认证请求。
S256 发送 verifier 的哈希,兑换时验证原值。state 和 nonce 都应关联当前会话。返回后按各自位置核对,并避免重复消费。
10.3 登录成功后为什么要更换 Session ID?
出现公司:暂无已核验的公开来源(本站自测)
考察重点:会话固定、权限提升与旧状态撤销。
相关内容:会话固定与失效。
参考回答
更换 Session ID 可阻断攻击者预先固定的会话。
认证后使用新 ID,并使旧 ID 失效。
权限提升时也应重新生成 ID。登出需撤销服务端状态。只删除浏览器 Cookie 会留下可重用的会话。