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

使用JWT Token获取ClaimTypes.NameIdentifier返回Null问题求助

问题:ASP.NET Core中JWT Token无法获取ClaimTypes.NameIdentifier值

在ASP.NET Core中使用JWT Token进行身份验证,调用BookDoctor接口时,通过var currentUser = User.FindFirst(ClaimTypes.NameIdentifier).Value;获取用户ID返回Null。

问题接口代码

[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
[HttpPost("BookDoctor")]
public async Task<IActionResult> BookDoctor(PatientAppointmentDto model)
{
    try
    {
        if (!ModelState.IsValid)
        {
            return BadRequest();
        }

        var isAvailable =await appoinmentService.CheckAvailability(model.DoctorId, model.Date, model.TimeStart);

        if (!isAvailable)
        {
            return BadRequest("Doctor not available");
        }

        model.TimeEnd = model.TimeStart.AddMinutes(30);
        var currentUser = User.FindFirst(ClaimTypes.NameIdentifier).Value;
        
        await appoinmentService.AddAsync(model.Info,
            model.Date, model.TimeStart, model.TimeEnd,
            model.DoctorId, currentUser.ToString());
        
        return Ok(model.Id);
    }
    catch(Exception ex)
    {
        return BadRequest(ex.Message);
    }
}

JWT Token生成方法

private async Task<JwtSecurityToken> CreateJwtToken(ApplicationUser user)
{
    var userClaims = await _userManager.GetClaimsAsync(user);
    var roles = await _userManager.GetRolesAsync(user);
    var roleClaims = new List<Claim>();

    foreach (var role in roles)
        roleClaims.Add(new Claim("roles", role));

    var claims = new[]
           {
               new Claim(JwtRegisteredClaimNames.Sub, user.Name),
               new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
               new Claim(JwtRegisteredClaimNames.Email, user.Email),
               new Claim(ClaimTypes.NameIdentifier, user.Id) // User ID
           }
           .Union(userClaims)
           .Union(roleClaims);

    var Key = _IConfiguration["JWT:key"];
    var issuer = _IConfiguration["JWT:issuer"];
    var audience = _IConfiguration["JWT:Audience"];
    var dur = _IConfiguration["JWT:DurationInDays"];
    var symmetricSecurityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Key));
    var signingCredentials = new SigningCredentials(symmetricSecurityKey, SecurityAlgorithms.HmacSha256);

    var jwtSecurityToken = new JwtSecurityToken(
               issuer: issuer,
               audience: audience,
               claims: claims,
               expires: DateTime.Now.AddDays(double.Parse(dur)),
               signingCredentials: signingCredentials);
}

Program.cs中的JWT配置

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(option =>
{
    option.RequireHttpsMetadata = false;
    option.SaveToken = false;
    option.TokenValidationParameters = new TokenValidationParameters
    {
        ValidateIssuerSigningKey = true,
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidateLifetime = true,
        ValidIssuer = builder.Configuration["JWT:Issuer"],
        ValidAudience = builder.Configuration["JWT:Audience"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["JWT:Key"]))
    };
});

排查与解决方案

  1. 修复Token生成方法的返回值
    你的CreateJwtToken方法未返回生成的jwtSecurityToken对象,导致实际签发的Token不包含任何声明。必须添加返回语句:

    private async Task<JwtSecurityToken> CreateJwtToken(ApplicationUser user)
    {
        // 原有代码...
        
        var jwtSecurityToken = new JwtSecurityToken(
            issuer: issuer,
            audience: audience,
            claims: claims,
            expires: DateTime.Now.AddDays(double.Parse(dur)),
            signingCredentials: signingCredentials);
        
        return jwtSecurityToken; // 添加此行返回Token
    }
    
  2. 验证Claim类型与解析映射
    ClaimTypes.NameIdentifier对应的完整类型是http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier,JWT中间件会自动解析该类型。如果仍无法获取,可以尝试:

    • 改用JWT标准声明存储用户ID:
      // 生成Token时替换为
      new Claim(JwtRegisteredClaimNames.Sub, user.Id)
      // 获取时使用
      var currentUser = User.FindFirst(JwtRegisteredClaimNames.Sub)?.Value;
      
    • 或在Token验证参数中明确声明类型映射:
      option.TokenValidationParameters = new TokenValidationParameters
      {
          // 原有配置...
          NameClaimType = ClaimTypes.NameIdentifier,
          RoleClaimType = "roles"
      };
      
  3. 确认中间件顺序正确
    在Program.cs中,UseAuthentication必须在UseAuthorization之前执行,否则认证信息无法被正确加载:

    app.UseAuthentication();
    app.UseAuthorization();
    
  4. 检查Token内容
    手动解码生成的Token,确认Payload中是否包含对应的用户ID声明。如果声明不存在,说明Token生成过程存在问题;如果存在但无法获取,需检查中间件配置是否正确解析声明。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 21:43:17