设计目标
- Access Token 15 分钟过期,Refresh Token 7 天。
- Access 过期前 5 分钟内由网关静默续期。
- 用户登出时 Refresh 进入 Redis 黑名单。
安全提醒
JWT 一旦签发无法撤销,所以必须配合 Redis 黑名单才能安全登出。不要把 JWT 当作唯一的会话凭据。
依赖
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.6</version>
</dependency>核心代码
@Service
public class JwtService {
@Value("${jwt.secret}") private String secret;
@Autowired private RedisTemplate<String, String> redis;
public String issueAccess(String uid) {
return Jwts.builder()
.subject(uid)
.issuedAt(new Date())
.expiration(new Date(System.currentTimeMillis() + 15 * 60_000))
.signWith(Keys.hmacShaKeyFor(secret.getBytes()))
.compact();
}
public boolean isRevoked(String jti) {
return redis.hasKey("jwt:blacklist:" + jti);
}
public void revoke(String jti, long ttl) {
redis.opsForValue().set("jwt:blacklist:" + jti, "1", ttl, TimeUnit.SECONDS);
}
}流程
| 阶段 | 客户端 | 服务端 |
|---|---|---|
| 登录 | 提交账号密码 | 签发 access + refresh,refresh 存 Redis |
| 请求 | 带 access | 网关校验 + 剩余 5 分钟则续签 |
| 刷新 | 带 refresh | 校验 Redis,重发一对 |
| 登出 | 带 access | jti 写黑名单,删除 refresh |
小结
这套方案在并发场景下足够稳,单实例 QPS 约 3k。如果你的体量更大,可以引入网关层的本地缓存减少 Redis 查询。