JWT刷新Token(Refresh Token)机制的核心是:用一个长期有效的Refresh Token换取新的短期Access Token,避免用户频繁登录,同时提升安全性。C#中实现的关键在于分离两种Token的生命周期、存储Refresh Token的安全方式,以及提供可靠的刷新接口。
Access Token与Refresh Token职责分离
Access Token用于每次API请求的身份校验,有效期短(如15–30分钟),不存数据库;Refresh Token用于获取新Access Token,有效期长(如7天),必须安全持久化(如Redis或加密后存数据库)。
Access Token只含必要声明(如sub、
exp、
role),不存敏感信息 Refresh Token建议带唯一标识(
jti)、绑定用户ID、设备指纹或IP(可选),便于后续吊销 生成时使用不同密钥或不同签名算法(如Access用HS256,Refresh用RS256+私钥签名)更佳
服务端生成与验证逻辑(.NET 6/7/8)
以ASP.NET Core为例,在登录成功后同时签发两个Token:
用Microsoft.IdentityModel.Tokens和
System.IdentityModel.Tokens.Jwt生成JWT Access Token设置短
Expires(如
DateTime.UtcNow.AddMinutes(20)) Refresh Token用随机安全字符串生成(
RandomNumberGenerator),加密后存入Redis(键为
refresh:{userId}:{jti},过期时间设为7天)
响应体返回{ accessToken: "...", refreshToken: "..." },Refresh Token通过HttpOnlyCookie返回更安全(避免JS读取)
刷新接口(/api/auth/refresh)实现要点
该接口需校验Refresh Token有效性,并签发新Access Token:
从Cookie或请求Body中提取Refresh Token 解码并验证签名、未过期、且jti在Redis中存在(查
refresh:{userId}:{jti})
若验证通过,删除旧Refresh Token(防重放),生成新Access Token + 新Refresh Token
将新Refresh Token再次存入Redis(同上键名,新jti),返回新Access Token 若失败(如Token不存在、已被撤销、用户已禁用),返回401并清空客户端Refresh Token
安全增强建议
仅基础刷新不够,还需防范常见风险:
每次刷新后更新Refresh Token(即“滚动刷新”),旧Token立即失效 记录Refresh Token使用时间与IP,异常频次(如1小时内多次刷新)触发风控 用户登出时主动删除Redis中所有该用户的Refresh Token(可用Redis前缀扫描+批量删除) 敏感操作(如改密码、删账号)强制使全部Refresh Token失效 前端在收到401且错误码为token_expired时自动调用刷新;失败则跳转登录页
基本上就这些。核心不是“怎么生成JWT”,而是“如何安全地管理Refresh Token的生命周期”。只要把存储、验证、吊销三个环节做扎实,机制就稳了。
