Angular/.NET Core应用:无需生成新Token能否刷新JWT过期时间?
能否仅延长JWT Token的过期时间而不生成新Token?
我拥有一个Angular/.NET Core应用,希望仅刷新Token的过期时间(例如增加1小时),而无需刷新或生成新的Token。请问这是否可行,还是必须生成新的Token?以下是我在应用认证时最初生成Token的代码:
var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new[] { new Claim(ClaimTypes.Name, loginModel.UserName), new Claim(ClaimTypes.Rsa, company.Name), new Claim(ClaimTypes.PrimarySid, company.Id.ToString()), new Claim(ClaimTypes.NameIdentifier, ap.Language), new Claim(ClaimTypes.IsPersistent, loginModel.RememberMe.ToString()), new Claim(ClaimTypes.Expiration, loginModel.RememberMe ? DateTime.Now.AddHours(1).ToString() : DateTime.Now.AddHours(1).ToString()), new Claim(ClaimTypes.Actor, employeeIdentifier) }), }; foreach (string r in Role) { tokenDescriptor.Subject.AddClaims(new[] { new Claim(ClaimTypes.Role, r) }); } var token = new JwtSecurityToken( issuer: _configuration["Token:Issuer"], audience: _configuration["Token:Audience"], claims: tokenDescriptor.Subject.Claims, expires: loginModel.RememberMe ? DateTime.Now.AddHours(1) : DateTime.Now.AddHours(1), notBefore: DateTime.Now, signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Token:Key"])), SecurityAlgorithms.HmacSha512) ); string tokenstring = new JwtSecurityTokenHandler().WriteToken(token); try { JwtKeys key = new JwtKeys() { jwtKey = tokenstring, userId = ap.UserName }; _db.Entry(key).State = EntityState.Added; _db.SaveChanges(); }
首先直接给结论:很遗憾,这是不可行的——你必须生成一个新的JWT Token来延长过期时间。
原因解释:
JWT的核心特性是自包含且不可篡改。一旦Token被签名生成后,它的所有内容(包括exp过期时间字段)都和签名绑定在一起。如果直接修改Token里的过期时间,签名验证会失败,服务端会直接拒绝这个被篡改的Token。这是JWT保证安全性的关键机制,所以没有办法绕过签名去修改已生成Token的任何内容。
替代方案:复用原Token的Claims生成新Token
虽然不能直接修改旧Token,但你可以解析并复用旧Token中的所有Claims,只更新过期时间,快速生成一个新的Token,这个流程对前端来说体验和“刷新过期时间”几乎一致。
这里给你一个示例实现:
public async Task<string> RefreshTokenExpiration(string oldToken) { var tokenHandler = new JwtSecurityTokenHandler(); var validationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, // 先验证旧Token是否还没过期(或允许短时间过期容错) ValidateIssuerSigningKey = true, ValidIssuer = _configuration["Token:Issuer"], ValidAudience = _configuration["Token:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Token:Key"])) }; try { // 验证并解析旧Token的Claims ClaimsPrincipal principal = tokenHandler.ValidateToken(oldToken, validationParameters, out SecurityToken validatedToken); var jwtToken = validatedToken as JwtSecurityToken; if (jwtToken == null || !jwtToken.Header.Alg.Equals(SecurityAlgorithms.HmacSha512, StringComparison.InvariantCultureIgnoreCase)) { throw new SecurityTokenException("Invalid token"); } // 复用原有的Claims,只更新过期时间 var newToken = new JwtSecurityToken( issuer: _configuration["Token:Issuer"], audience: _configuration["Token:Audience"], claims: principal.Claims, expires: DateTime.Now.AddHours(1), // 设置新的过期时间 notBefore: DateTime.Now, signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Token:Key"])), SecurityAlgorithms.HmacSha512) ); string newTokenString = tokenHandler.WriteToken(newToken); // 更新数据库中的Token记录(替换旧Token为新Token) var existingKey = await _db.JwtKeys.FirstOrDefaultAsync(k => k.jwtKey == oldToken); if (existingKey != null) { existingKey.jwtKey = newTokenString; _db.Entry(existingKey).State = EntityState.Modified; await _db.SaveChangesAsync(); } return newTokenString; } catch (Exception ex) { // 处理验证失败或其他错误 throw new Exception("Failed to refresh token expiration", ex); } }
额外注意事项:
- 一定要先验证旧Token的有效性(签名正确、未过期,或者允许短时间的过期缓冲),避免恶意请求滥用刷新流程。
- 如果你的应用使用了Refresh Token机制,建议结合Refresh Token来做这个流程——用有效的Refresh Token来获取新的Access Token,这样安全性更高。
- 前端需要将新获取的Token替换掉本地存储的旧Token,后续请求使用新Token。
内容的提问来源于stack exchange,提问作者zarzou
相关产品推荐
相关产品推荐

