143 lines
7.1 KiB
Markdown
143 lines
7.1 KiB
Markdown
|
|
---
|
|||
|
|
tags: [test/review, auth, pattern, oauth2]
|
|||
|
|
create time: 2026-08-09 12:00
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# OAuth2 与 JWT — 测试题
|
|||
|
|
|
|||
|
|
## 概述
|
|||
|
|
本测试覆盖 OAuth2 四种授权模式、JWT 结构(Header/Payload/Signature)、HS256 vs RS256、Refresh Token 轮换机制以及 Token 黑名单策略。共 10 道题目(6 选择 + 3 填空 + 1 简答)。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、选择题(6道,由浅入深)
|
|||
|
|
|
|||
|
|
> **难度阶梯**: Q1-Q2 基础概念 → Q3-Q4 核心原理 → Q5-Q6 深入应用/边界场景
|
|||
|
|
|
|||
|
|
### Q1(基础)— 考察定义层面
|
|||
|
|
|
|||
|
|
OAuth2 中目前最推荐的安全授权模式是:
|
|||
|
|
|
|||
|
|
A. Authorization Code + PKCE
|
|||
|
|
B. Implicit
|
|||
|
|
C. Password
|
|||
|
|
D. Client Credentials
|
|||
|
|
|
|||
|
|
### Q2(基础)→
|
|||
|
|
|
|||
|
|
以下哪种 OAuth2 授权模式**不需要用户参与**?
|
|||
|
|
|
|||
|
|
A. Authorization Code
|
|||
|
|
B. Implicit
|
|||
|
|
C. Password
|
|||
|
|
D. Client Credentials
|
|||
|
|
|
|||
|
|
### Q3(进阶)— 核心原理
|
|||
|
|
|
|||
|
|
JWT 的 Header + Payload → Signature 的计算过程是:
|
|||
|
|
|
|||
|
|
A. base64UrlEncode(header) + "." + base64UrlEncode(payload),然后用 secret 或私钥签名
|
|||
|
|
B. 直接将三个部分拼接后编码为 Base64
|
|||
|
|
C. 将 payload 用私钥加密
|
|||
|
|
D. 将 header 和 payload 分别签名后拼接
|
|||
|
|
|
|||
|
|
### Q4(进阶)— 比较/辨析
|
|||
|
|
|
|||
|
|
微服务架构为什么推荐 RS256(非对称)而不是 HS256(对称)?
|
|||
|
|
|
|||
|
|
A. RS256 性能更好
|
|||
|
|
B. 每个微服务只需验证公钥而不需要持有签发私钥,即使某个服务被攻陷也无法伪造其他服务的 token
|
|||
|
|
C. HS256 不支持自定义 claim
|
|||
|
|
D. RS256 不需要设置 exp 过期时间
|
|||
|
|
|
|||
|
|
### Q5(深入)— 场景推理
|
|||
|
|
|
|||
|
|
在 Refresh Token 轮换机制中,如果同一个 Refresh Token RT1 被使用了两次(第一次正常刷新生成了 RT2+AT2,第二次攻击者重放了旧的 RT1),第二次的处理策略是什么?
|
|||
|
|
|
|||
|
|
A. 正常刷新生成新的 RT3+AT3
|
|||
|
|
B. 忽略重复请求返回之前的 AT2
|
|||
|
|
C. 级联销毁该用户的所有 token 并要求重新登录
|
|||
|
|
D. 只冻结 RT1 但不影响其他 token
|
|||
|
|
|
|||
|
|
### Q6(深入)— 源码级/边界场景
|
|||
|
|
|
|||
|
|
关于 JWT 的使用,以下哪个做法是错误的?
|
|||
|
|
|
|||
|
|
A. Access Token 设置为短生命周期(如 5~15 分钟)
|
|||
|
|
B. Refresh Token 存放在 HttpOnly Cookie 而非 localStorage
|
|||
|
|
C. 把用户密码放在 JWT payload 中以方便验签时读取
|
|||
|
|
D. RS256 模式下验证方只用公钥本地验签零网络调用
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、填空题(3道)
|
|||
|
|
|
|||
|
|
### F1 — 填空1
|
|||
|
|
|
|||
|
|
JWT 标准保留声明(Registered Claims)包括六个:`iss`(_____)、`sub`(主题/用户标识)、`aud`(_____)、`exp`(过期时间)、`iat`(签发时间)、`jti`(JWT ID 唯一标识支持撤销)。请填写其中两个中文名称。
|
|||
|
|
|
|||
|
|
> **提示**: iss = Issuer, aud = Audience。
|
|||
|
|
|
|||
|
|
### F2 — 填空2
|
|||
|
|
|
|||
|
|
Token 管理常用的混合策略是:**短生命周期 Access Token(5 分钟)** + 本地校验(无需网络查询);**Refresh Token 存储在_____**每次刷新做一次性校验;特殊场景下的**黑名单**用于主动登出和密码修改后的批量踢人。
|
|||
|
|
|
|||
|
|
> **提示**: 回忆原文 Token 管理混合策略的描述。
|
|||
|
|
|
|||
|
|
### F3 — 填空3
|
|||
|
|
|
|||
|
|
PKCE(Proof Key for Code Exchange)通过 `code_verifier` / `code_challenge` 对替代 `client_secret`,使 Authorization Code 对所有客户端类型(包括无法安全存储 client_secret 的_____ App 和 SPA)都是安全的。
|
|||
|
|
|
|||
|
|
> **提示**: PKCE 解决的问题是让没有秘密的客户端也能安全使用 Authorization Code 模式。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、简答题(1道)
|
|||
|
|
|
|||
|
|
### S1
|
|||
|
|
|
|||
|
|
面试官问:"某系统的认证架构如下:前端收到 AT(Access Token)存在 localStorage 中,后端用 HS256 签名,RT(Refresh Token)也放在 localStorage 里每次刷新再生成新 RT。请指出这个设计中的至少三个安全问题并给出改进方案。"
|
|||
|
|
|
|||
|
|
> **答题框架提示**:
|
|||
|
|
> 1. Token 存储位置的安全性
|
|||
|
|
> 2. 签名算法的选择
|
|||
|
|
> 3. Refresh Token 的轮换安全性
|
|||
|
|
> 4. 补充:是否还有其他可改进之处
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 参考答案与解析
|
|||
|
|
|
|||
|
|
### 选择题答案
|
|||
|
|
|
|||
|
|
| 题号 | 正确答案 | 解析 |
|
|||
|
|
|------|---------|------|
|
|||
|
|
| Q1 | A | Authorization Code + PKCE 是当前最推荐的方案。Code 在后端交换(浏览器拿不到 token),PKCE 进一步解决了 SPA/Mobile 无法保护 client_secret 的问题。Implicit 已废弃,Password 仅限第一方应用。 |
|
|||
|
|
| Q2 | D | Client Credentials 没有用户参与——客户端用自己的身份(client_id + client_secret)申请令牌。典型场景:后台定时任务、微服务间内部调用、CI/CD 流水线。 |
|
|||
|
|
| Q3 | A | 标准的 JWT 签名计算流程:base64UrlEncode(header) + "." + base64UrlEncode(payload),然后 HMACSHA256 或用 RSA 私钥签名。Base64 是可逆编码不是加密。 |
|
|||
|
|
| Q4 | B | RS256 的核心优势是每个服务只需公钥就能验证——即使某台服务被攻陷,攻击者只有公钥无法伪造 token(因为签名需要私钥)。HS256 要求所有服务共享同一个密钥,任何一台泄漏导致全局崩溃。 |
|
|||
|
|
| Q5 | C | 原文明确:如果同一个 Refresh Token 出现两次,第二次判定为窃听攻击,同时**级联销毁该用户的所有 token 并要求重新登录**。这是最安全的防御策略。 |
|
|||
|
|
| Q6 | C | JWT 只是 Base64 编码而非加密,任何人都可以解码阅读 payload。**绝对不要把敏感信息放在 JWT payload 中**。如果需要保密应使用 JWE(加密型 JWT)。 |
|
|||
|
|
|
|||
|
|
### 填空题答案
|
|||
|
|
|
|||
|
|
| 题号 | 答案 | 解析 |
|
|||
|
|
|------|------|------|
|
|||
|
|
| F1 | `Issuer(签发者)`;`Audience(接收方)` | 六大标准声明中,iss 标识谁签发的,aud 标识谁应该接收这个 token。配合 exp(过期时间)实现完整的生命周期控制。jti 提供撤销能力。 |
|
|||
|
|
| F2 | `Redis` | 混合策略的三段论:① 短 AT 本地验证;② RT 存 Redis 单次校验防重放;③ 黑名单应对特殊情况。这种组合兼顾性能和安全性。 |
|
|||
|
|
| F3 | `移动`(或"Mobile") | RFC 7636 定义的 PKCE 让 Authorization Code 模式适用于所有客户端类型——不仅是传统的有后端的服务,也包括无法安全存储 client_secret 的移动 App 和 SPA。 |
|
|||
|
|
|
|||
|
|
### 简答题参考答案
|
|||
|
|
|
|||
|
|
S1:**参考答案要点**:
|
|||
|
|
1. **localStorage 安全风险**:AT 和 RT 都存在 localStorage 中容易被 XSS 窃取。改进:AT 可以放在内存变量中(页面刷新需重新登录),RT 必须放在 HttpOnly Cookie(JS 无法读取)。
|
|||
|
|
2. **HS256 密钥泄露风险**:所有微服务共享同一个 secret,一旦某台服务器被攻陷全局信任崩溃。改进:改用 RS256,各服务用不同公钥独立验证。
|
|||
|
|
3. **Refresh Token 未旋转**:虽然每次生成新 RT,但如果缺少"同一 RT 出现两次触发级联吊销"的检测,攻击者可以用旧 RT 无限次重放而不会被发现。改进:增加 RT 消费记录检查逻辑。
|
|||
|
|
4. **补充 - 缺少 state 防护**:Authorization Code 回调时未校验 state 参数可能导致 CSRF 攻击。改进:生成随机 state 存 cookie 中,回调时比对。
|
|||
|
|
5. **补充 - 无 token 黑名单**:用户登出或改密码后无法立即吊销已发出的 AT。改进:引入 Redis 黑名单或利用短生命周期 + RT 强制重新认证缓解。
|
|||
|
|
|
|||
|
|
**评分标准**:答出任意 2 个要点即可得满分;完全正确需覆盖全部要点。
|
|||
|
|
|
|||
|
|
## 关联笔记
|
|||
|
|
- [[RBAC 权限模型]]
|