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

JWT令牌签名无效且过期时间不生效问题排查求助

解决JWT签名无效(Invalid signature)及过期时间校验失效问题

问题原因分析

签名无效

  1. 密钥长度不达标:HmacSha256签名算法要求密钥至少为128位(16个ASCII字符),如果Constansts.JWT_SECURITY_KEY_FOR_TOKEN长度不足,会导致令牌生成与验证时的密钥字节数组不匹配,触发签名无效错误。
  2. 自定义策略绕过框架验证:UserPolicy中直接调用ReadJwtToken解析令牌,完全跳过了JWT中间件的签名校验流程,即使令牌签名无效,仍会执行后续权限判断逻辑。

过期时间校验失效

  1. 未利用框架内置校验:AddJwtBearer配置的ValidateLifetime=true未生效,因为自定义授权策略没有依赖框架的验证结果,而是手动解析令牌内容,绕开了过期时间校验。
  2. 时区差异问题:生成令牌时使用DateTime.Now(本地时间),而JWT框架默认采用UTC时间进行过期校验,可能导致时间判断偏差。

解决方案

1. 修复签名无效问题

  • 确保密钥符合算法要求:检查Constansts.JWT_SECURITY_KEY_FOR_TOKEN,确保其长度至少为16个ASCII字符(例如"your-secure-secret-key-min-16-chars")。
  • 依赖框架完成签名校验:自定义授权策略中不再手动解析令牌,而是通过context.User获取已通过框架校验的Claims,只有通过JWT中间件验证的请求才会进入授权逻辑。

2. 修复过期时间校验失效问题

  • 启用框架生命周期校验:移除自定义策略中手动解析令牌的代码,依赖AddJwtBearer配置的ValidateLifetime=true和ClockSkew=TimeSpan.Zero自动完成过期时间校验。
  • 生成令牌使用UTC时间:将令牌过期时间的生成逻辑从DateTime.Now改为DateTime.UtcNow,避免时区差异导致的校验错误。

修改后的代码示例

调整JWT令牌生成管理器

// 将本地时间改为UTC时间生成过期时间
var tokenExpireTimeStamp = DateTime.UtcNow.AddMinutes(Constansts.JWT_TOKEN_EXPIRE_TIME);

修改自定义授权策略

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserPolicyRequirement requirement)
{
    // 从已验证的context.User中获取用户ID,跳过手动解析令牌
    var userIdClaim = context.User.FindFirst("userId");
    if (userIdClaim == null)
    {
        context.Fail();
        return Task.CompletedTask;
    }

    var request = _contextAccessor.HttpContext?.Request;
    string actionName = request.RouteValues["action"].ToString();
    string controllerName = request.RouteValues["controller"].ToString();
    var userId = userIdClaim.Value;

    if (dbContext.userAccessActions.Any(a => a.UserId == userId && a.ActionName == actionName && a.ControllName == controllerName))
    {
        context.Succeed(requirement);
    }
    else
    {
        context.Fail();
    }

    return Task.CompletedTask;
}

补充JWT验证配置(可选,避免额外校验失败)

当前配置中ValidateAudience=true但未指定ValidAudience,如果生成令牌时也未设置Audience,会触发额外校验错误,建议补充配置:

options.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes(Constansts.JWT_SECURITY_KEY_FOR_TOKEN)),
    ValidateAudience = true,
    ValidAudience = "your-api-audience", // 例如你的API域名
    ValidateIssuer = true,
    ValidIssuer = "your-auth-service", // 例如你的认证服务标识
    ValidateLifetime = true,
    ClockSkew = TimeSpan.Zero,
    RequireExpirationTime = true,
    RequireSignedTokens = true
};

同时在生成令牌的SecurityTokenDescriptor中添加对应配置:

var securityTokenDescriptor = new SecurityTokenDescriptor
{
    Subject = new ClaimsIdentity(List),
    Expires = tokenExpireTimeStamp,
    Audience = "your-api-audience",
    Issuer = "your-auth-service",
    SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(tokenKey), SecurityAlgorithms.HmacSha256Signature)
};

额外注意事项

  • 确保Constansts.JWT_SECURITY_KEY_FOR_TOKEN在令牌生成与验证环节完全一致,无空格、大小写差异。
  • 生产环境必须开启RequireHttpsMetadata=true,防止令牌被窃听。

内容的提问来源于stack exchange,提问作者sadegh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:24:57