共计 2344 个字符,预计需要花费 6 分钟才能阅读完成。
在分布式系统中,skill 和 mcp 服务的 token 管理一直是个棘手的问题。特别是在微服务架构下,token 的安全性、并发控制和生命周期管理常常让人头疼。今天我们就来聊聊如何用 JWT 和 OAuth 2.0 的混合方案,结合 Redis 实现一套安全高效的 token 管理机制。

常见痛点分析
在分布式环境下,我们经常遇到这些 token 管理难题:
- 敏感 token 如何安全存储和传输
- 高并发场景下的验证性能瓶颈
- 跨服务调用时的 token 传递问题
- token 过期和刷新机制的实现
- 防止 token 泄露和重放攻击
技术方案设计
混合架构方案
我们采用 JWT + OAuth 2.0 的混合架构:
- JWT 负责携带用户声明信息
- OAuth 2.0 提供标准的授权流程
- Redis 处理 token 黑名单和会话状态
分层加密策略
为了兼顾性能和安全性:
- 使用 HS256 算法签发短期 access token(5 分钟)
- 使用 RS256 算法签发长期 refresh token(7 天)
- 敏感操作需要二次验证
Redis 黑名单实现
核心流程:
- 用户注销或 token 过期时加入黑名单
- 验证 token 时先检查黑名单
- 设置合理的 TTL 自动清理
代码实现
Token 生成示例(Spring Boot)
// JWT 工具类核心方法
public class JwtUtil {
// 生成 access token
public String generateAccessToken(UserDetails user) {return Jwts.builder()
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + ACCESS_EXPIRE))
.signWith(SignatureAlgorithm.HS256, SECRET_KEY)
.compact();}
// 生成 refresh token
public String generateRefreshToken(UserDetails user) {return Jwts.builder()
.setSubject(user.getUsername())
.setIssuedAt(new Date())
.setExpiration(new Date(System.currentTimeMillis() + REFRESH_EXPIRE))
.signWith(SignatureAlgorithm.RS256, privateKey)
.compact();}
}
Token 验证拦截器
public class TokenInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
// 1. 从 header 提取 token
String token = extractToken(request);
// 2. 检查黑名单
if (redisTemplate.opsForValue().get("blacklist:"+token) != null) {throw new InvalidTokenException("Token 已失效");
}
// 3. 验证 JWT 有效性
Claims claims = Jwts.parser()
.setSigningKey(SECRET_KEY)
.parseClaimsJws(token)
.getBody();
// 4. 将用户信息存入请求上下文
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(claims.getSubject(), null, emptyList())
);
return true;
}
}
性能优化
加密算法对比测试
| 算法类型 | 签名速度 (ops/s) | 验证速度 (ops/s) |
|---|---|---|
| HS256 | 45,000 | 55,000 |
| RS256 | 1,200 | 500 |
Redis 集群性能
- 单节点 QPS:~80,000
- 3 节点集群 QPS:~220,000
- 黑名单查询平均延迟:1.2ms
安全防护
防范重放攻击
- 强制使用 HTTPS 传输
- 在 JWT 中加入 jti(唯一标识)
- 短期 token 有效期(建议 5 -15 分钟)
- 关键操作要求 nonce 参数
Token 泄漏处理
应急流程:
- 立即将 token 加入黑名单
- 通知用户修改密码
- 审计相关操作日志
- 必要时重置用户所有会话
避坑指南
时钟漂移问题
当服务器时间不同步时:
- 配置 NTP 时间同步服务
- 在 JWT 验证时允许 1 - 2 分钟误差
- 使用分布式时钟服务
分布式锁的正确使用
错误做法:
// 错误的锁释放方式
try {lock.lock();
// 业务代码
} finally {lock.unlock(); // 可能释放别人的锁
}
正确做法:
String requestId = UUID.randomUUID().toString();
try {boolean acquired = redisLock.acquire("key", requestId, 30, TimeUnit.SECONDS);
if (acquired) {// 业务代码}
} finally {redisLock.release("key", requestId);
}
总结与思考
这套方案在我们生产环境支撑了日均千万级的 token 验证请求。完整示例代码已放在 GitHub:token-management-demo
留给大家一个思考题:如何设计 token 的自动续期机制,既能保证用户体验,又不降低安全性?欢迎在评论区分享你的方案。
正文完
