刷新 JWT 过期而不刷新或生成新 Token

Posted

技术标签:

【中文标题】刷新 JWT 过期而不刷新或生成新 Token【英文标题】:Refresh JWT expiration without refreshing or generating a new Token 【发布时间】:2021-04-06 23:19:34 【问题描述】:

我有一个 Angular/.NET Core 应用程序, 我只想刷新令牌的到期时间(例如添加 1 小时),而不刷新和生成新令牌。 我可以点它还是我需要生成一个新的令牌?

这是我在对应用进行身份验证时首先生成令牌的方式:

  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();
            

有什么帮助吗?谢谢

【问题讨论】:

更改令牌中的任何内容实际上意味着创建一个新令牌。令牌已签名,负载的任何更改都会使签名无效,因此需要再次签名,因此最好的方法是使用刷新令牌。 @jps 谢谢,你能给我任何简单的实现刷新令牌的例子吗? 【参考方案1】:

令牌生成后,不能以任何方式更改。您必须生成一个新令牌才能刷新它。

更好的方法是.net core发送一个token和过期时间(计算具体时间,比如10:00加一小时,改成11:00)到angular。

当用户在 10:55 到 11:00 之间访问应用程序时,客户端无需重新登录即可发送刷新请求。当时间超过 11:00 时,用户需要重新登录。

这是一个例子。同时生成截止日期。

public IActionResult Authenticate(string username,string userpassword,string email)
    
        var user = new Users
        
            //...
        ;
        
        var tokenHandler = new JwtSecurityTokenHandler();
        var key = Encoding.ASCII.GetBytes("this is a public key");
        var authTime = DateTime.Now;
        var expiresAt = authTime.AddDays(7);
        var tokenDescriptor = new SecurityTokenDescriptor
        
            Subject = new ClaimsIdentity(new Claim[]
            
                new Claim(JwtClaimTypes.Audience,"api"),
                //...
            ),
            Expires = expiresAt,
            SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
        ;
        var token = tokenHandler.CreateToken(tokenDescriptor);
        var tokenString = tokenHandler.WriteToken(token);

        return Ok(new
        
            access_token = tokenString,
            expiresTime=DateTime.Now.AddHours(1)
        );
    

将json存入LocalStorage,请求时判断是否临近过期时间。

在 angualr 中,使最后期限减去五分钟。

 var deadline = (new Date(localStorage.getItem(''))).getTime();
if (deadline > (Date.now() - 60 * 60 * 1000)) 
    //refresh token

【讨论】:

是的,我希望在用户仍处于活动状态时刷新令牌或将到期时间延长 1 小时。您有任何示例如何执行此操作吗?谢谢

以上是关于刷新 JWT 过期而不刷新或生成新 Token的主要内容,如果未能解决你的问题,请参考以下文章

刷新令牌是不是需要过期的 JWT 才能创建新的访问令牌?

JWT刷新token策略

JWT刷新token策略

腾讯先锋怎么解决token过期

JWT生成token及过期处理方案

JWT, 为啥需要刷新令牌?