"采用 RS256 签名 + Redis 刷新令牌白名单"的技术实现。我来详细解释基于 Redis 实现的白名单和黑名单机制:
白名单 (Allow List)
含义
白名单机制:只允许列表中明确列出的项目通过,其他一律拒绝。
在认证系统中的具体应用
plain
// JWT 刷新令牌白名单
// 只有存在于 Redis 白名单中的刷新令牌才被认为是有效的
if (redis.exists("token_whitelist:" + refreshToken)) {
// 允许刷新访问令牌
return newAccessToken;
} else {
// 拒绝请求
throw new UnauthorizedException();
}
典型场景
- 令牌管理:有效的刷新令牌列表
- IP 访问控制:只允许特定 IP 访问管理后台
- 功能权限:只有白名单用户才能使用某些高级功能
黑名单 (Deny List/Blocklist)
含义
黑名单机制:拒绝列表中列出的项目,其他一律允许。
具体应用
plain
// 访问令牌黑名单:已注销但未过期的令牌
if (redis.exists("token_blacklist:" + accessToken)) {
// 拒绝访问
throw new UnauthorizedException("令牌已失效");
} else {
// 允许继续访问
return userInfo;
}
典型场景
- 令牌撤销:用户主动退出或管理员撤销令牌
- 恶意用户封禁:禁止违规用户访问
- 敏感操作限制:阻止某些危险操作
项目中的具体实现
根据文档描述,项目采用了白名单方案:
技术架构
plain
用户登录 → 生成双令牌(access_token + refresh_token)
→ 将 refresh_token 存入 Redis 白名单
→ 设置 7 天过期时间
优势对比
| 机制 | 优势 | 劣势 | 适用场景 |
|---|---|---|---|
| 白名单 | 安全性高,默认拒绝 | 存储开销大 | 刷新令牌管理 |
| 黑名单 | 存储效率高,默认允许 | 实时性要求高 | 访问令牌撤销 |
为什么选择白名单?
文档中采用白名单是因为:
- 安全性优先:只有明确授权的刷新令牌才能使用
- 会话控制:支持即时令牌撤销(从白名单删除即可)
- 性能考量:刷新令牌使用频率远低于访问令牌
实际业务场景示例
plain
// 令牌刷新
public TokenRefreshResponse refreshToken(String refreshToken) {
// 检查白名单
if (!redis.exists("whitelist:refresh:" + refreshToken)) {
throw new UnauthorizedException("刷新令牌无效");
}
// 生成新的访问令牌
String newAccessToken = generateAccessToken();
return new TokenRefreshResponse(newAccessToken);
}
// 用户登出
public void logout(String refreshToken) {
// 从白名单中移除(即时撤销)
redis.del("whitelist:refresh:" + refreshToken);
}
这种设计确保了认证系统的高安全性和良好的用户体验。