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

为何JwtSecurityTokenHandler读取的Token字段少于jwt.io?求排查

JWT验证异常:ReadJwtToken无法读取exp等字段

问题现象

  • 在ValidateToken接口中,通过JwtSecurityTokenHandler.ReadJwtToken解析JWT时,发现缺失exp(值为1752128418)在内的3个字段
  • 打印Token并验证显示所有字段完整,但代码读取时jwt.Payload.Expiration为null
  • 使用与GenerateJwtToken完全一致的TokenValidationParameters执行验证,结果无变化
  • 其他使用该Token的授权端点可正常工作

验证方法代码

public async Task<ActionResult<object>> ValidateToken()
{
    var authHeader = HttpContext.Request.Headers["Authorization"].FirstOrDefault();
    
    var token = authHeader.Substring("Bearer ".Length).Trim();
    Console.WriteLine(token.ToString());
    var tokenHandler = new JwtSecurityTokenHandler();
    var jwt = tokenHandler.ReadJwtToken(token);
    
    if (jwt.Payload.Expiration == null)
    {
        return Unauthorized("Token missing 'exp' claim.");
    }
}

验证参数代码

var key = Encoding.UTF8.GetBytes(_config["Jwt:Key"]);
tokenHandler.ValidateToken(token, new TokenValidationParameters
{
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = new SymmetricSecurityKey(key),
    ValidateIssuer = true,
    ValidIssuer = _config["Jwt:Issuer"],
    ValidateAudience = true,
    ValidAudience = _config["Jwt:Audience"],
    ValidateLifetime = true,
    ClockSkew = TimeSpan.FromMinutes(1)
}, out SecurityToken validatedToken);

Token生成方法

private string GenerateJwtToken(Account account)
{
    var claims = new[]
    {
        new Claim(ClaimTypes.NameIdentifier, account.Id.ToString()),
        new Claim(ClaimTypes.Name, account.Username),
        new Claim(ClaimTypes.Role, account.Role.ToString())
    };

    var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
    var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
    var token = new JwtSecurityToken(
        issuer: _config["Jwt:Issuer"],
        audience: _config["Jwt:Audience"],
        claims: claims,
        expires: DateTime.UtcNow.AddDays(7),
        signingCredentials: creds
    );

    return new JwtSecurityTokenHandler().WriteToken(token);
}

引用命名空间

using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;

日志信息

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1laWRlbnRpZmllciI6IjEwIiwiaHR0cDovL3NjaGVtYXMueG1sc29hcC5vcmcvd3MvMjAwNS8wNS9pZGVudGl0eS9jbGFpbXMvbmFtZSI6Im1vc3RhZmHigIsiLCJodHRwOi8vc2NoZW1hcy5taWNyb3NvZnQuY29tL3dzLzIwMDgvMDYvaWRlbnRpdHkvY2xhaW1zL3JvbGUiOiJQbGF5ZXIiLCJleHAiOjE3NTIxMjg0MTgsImlzcyI6IkdhbWVTZXJ2ZXJBUEkiLCJhdWQiOiJHYW1lQ2xpZW50cyJ9.zMCtvt6lyHPbNMkUmyociTVUwPp81qwF1gcBaOzfsNo
{"alg":"HS256"}.{"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier":"10","http://schemas.microsoft.com/ws/2008/06/identity/claims/role":"Player","iss":"GameServerAPI"}

排查方向与解决方案

  1. 确认Token完整性
    在代码中添加Token长度校验,确保从Authorization头截取的Token与日志中完整Token一致:

    Console.WriteLine($"Token length: {token.Length}");
    

    若长度不一致,改用更安全的截取方式避免格式异常:

    var token = authHeader?.Replace("Bearer ", "", StringComparison.OrdinalIgnoreCase).Trim();
    
  2. 直接访问Payload原始字典
    部分标准字段可能因映射逻辑未赋值到对应属性,但会保留在Payload字典中,尝试直接读取:

    if (!jwt.Payload.TryGetValue("exp", out var expValue) || expValue == null)
    {
        return Unauthorized("Token missing 'exp' claim.");
    }
    // 转换为DateTime格式
    var expiration = DateTimeOffset.FromUnixTimeSeconds(long.Parse(expValue.ToString())).UtcDateTime;
    
  3. 检查JWT Handler配置
    确认是否设置了MapInboundClaims = false,该配置会关闭标准Claim的自动映射,导致Payload.Expiration等属性无法赋值:

    var tokenHandler = new JwtSecurityTokenHandler
    {
        MapInboundClaims = true // 确保为默认值true
    };
    
  4. 验证ValidateToken返回的Token
    调用ValidateToken后,将返回的validatedToken转换为JwtSecurityToken,验证流程可能修复字段映射问题:

    var validatedJwt = validatedToken as JwtSecurityToken;
    if (validatedJwt?.Payload.Expiration == null)
    {
        return Unauthorized("Token missing 'exp' claim.");
    }
    
  5. 检查NuGet包版本
    确保System.IdentityModel.Tokens.Jwt和Microsoft.IdentityModel.Tokens包版本一致且为最新稳定版,旧版本可能存在字段解析Bug。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 19:20:12