You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:25:48