.NET Core 7中JWT签名无效问题求助
问题排查与修复方案
你的JWT签名验证失败核心问题在于**exp和iat声明的格式错误**,JWT标准要求这两个字段必须是Unix时间戳(整数,单位为秒),而你代码里直接将DateTime转成字符串,导致Claims内容不符合规范,最终签名验证不通过。
修复步骤:
1. 修正exp和iat的生成方式
将DateTime转换为Unix时间戳(秒数)后再转成字符串:
// 计算Unix时间戳(秒) long expUnix = new DateTimeOffset(expiration).ToUnixTimeSeconds(); long iatUnix = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeSeconds(); List<Claim> claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, username), new Claim(JwtRegisteredClaimNames.Exp, expUnix.ToString()), new Claim(JwtRegisteredClaimNames.Sub, userID), new Claim(JwtRegisteredClaimNames.UniqueName, username), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Iat, iatUnix.ToString()), };
2. 更简洁的优化:让JwtSecurityToken自动处理exp和iat
JwtSecurityToken构造函数支持直接传入时间参数,会自动生成符合规范的iat和exp声明,无需手动添加,避免格式错误:
DateTime expiration = DateTime.UtcNow.AddMinutes(Convert.ToDouble(_configuration["AppSettings:JWT_EXP_TIME"])!); DateTime issuedAt = DateTime.UtcNow; List<Claim> claims = new List<Claim> { new Claim(ClaimTypes.NameIdentifier, username), new Claim(JwtRegisteredClaimNames.Sub, userID), new Claim(JwtRegisteredClaimNames.UniqueName, username), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), // 移除手动添加的exp和iat }; SymmetricSecurityKey key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(secretkey)); SigningCredentials credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); JwtSecurityToken token = new JwtSecurityToken( issuer: issuer, audience: audience, claims: claims, notBefore: issuedAt, expires: expiration, signingCredentials: credentials ); return new JwtSecurityTokenHandler().WriteToken(token);
额外验证点
- 确保jwt.io中输入的密钥和代码里的
secretkey完全一致,注意大小写、空格、特殊字符,避免复制粘贴时引入额外字符。 - 确认代码使用的算法是
SecurityAlgorithms.HmacSha256,jwt.io的算法选择需对应(默认HS256即可)。
内容的提问来源于stack exchange,提问作者Hossein Dadashi
相关产品推荐
相关产品推荐

