如何设置JWT Token长期有效期?100年期限提示无过期时间报错
问题分析与解决
问题重现
用户生成JWT的代码如下:
private string GenerateJSONWebToken(pswd user) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], null, expires: DateTime.Now.AddYears(100), signingCredentials: credentials); return new JwtSecurityTokenHandler().WriteToken(token); }
设置100年过期时间后,出现“no expiry”错误,Token无法访问目标Web API;但设置10年以内过期时间时,Token可正常工作并返回200状态码。
原因解析
JWT的exp(过期时间)声明采用Unix时间戳(从1970-01-01T00:00:00Z到目标时间的秒数),而32位Unix时间戳的最大值对应2038-01-19T03:14:07Z。当设置DateTime.Now.AddYears(100)时,该时间大概率会超过2038年,导致生成的Unix时间戳溢出,在JWT解析时会被判定为无效,甚至被误认为未设置exp声明,从而触发“no expiry”错误。此外,部分JWT验证库会对极端遥远的过期时间做特殊校验,直接判定为无效,也会引发该问题。
解决方案
1. 接近永久的合规有效期
若需要接近永久的有效期,建议将过期时间设置为2038年1月19日之前,避免32位时间戳溢出问题:
// 设置为2038年1月1日UTC时间,避开时间戳溢出临界点 var expires = new DateTime(2038, 1, 1, 0, 0, 0, DateTimeKind.Utc); var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], null, expires: expires, signingCredentials: credentials);
2. 不设置exp声明(不推荐)
若完全不需要过期时间,可以省略expires参数,生成不带exp声明的JWT。但这种方式会让Token永久有效,一旦泄露无法失效,存在严重安全隐患,仅适用于非敏感场景:
var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], null, signingCredentials: credentials);
3. 自定义永久有效逻辑(灵活可控)
可以添加自定义声明标记永久有效,再在API的JWT验证逻辑中跳过过期时间校验,兼顾安全性与需求:
生成Token时添加自定义声明
var claims = new[] { new Claim("permanent", "true") }; var token = new JwtSecurityToken(_config["Jwt:Issuer"], _config["Jwt:Issuer"], claims, signingCredentials: credentials);
验证时处理自定义声明(以ASP.NET Core为例)
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = _config["Jwt:Issuer"], ValidAudience = _config["Jwt:Issuer"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"])), // 自定义生命周期校验逻辑 LifetimeValidator = (before, expires, token, parameters) => { var permanentClaim = token.Claims.FirstOrDefault(c => c.Type == "permanent" && c.Value == "true"); if (permanentClaim != null) { return true; } // 无永久声明时按正常过期时间校验 return expires != null && expires > DateTime.UtcNow; } }; });
内容的提问来源于stack exchange,提问作者Yuvraj Jadhav
相关产品推荐
相关产品推荐

