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

API无法正确获取JWT Token中除ID外的用户信息排查

问题:JWT认证后GetCurrentUser接口仅能获取用户ID,其余信息为null

我正在开发应用的认证模块,用户可成功注册并登录,信息已存入SQL数据库。但在UserController中创建GetCurrentUser方法后,该接口仅能获取到用户ID,其余用户信息均无法正确获取。我已确认Token包含所需的全部用户信息,但接口返回除ID外均为null。


登录方法代码

[HttpPost]
[Route("Login")]
public async Task<IActionResult> Login(UserLoginRequestModel loginRequest)
{
    var user = await accountService.Validate(loginRequest.Email, loginRequest.Password);
    if(user == null)
    {
        return Unauthorized("Invalid Username or Password");
    }
    var token = GenerateJWT(user);
    var tokenValue = new { jwt = token };
    return Ok(tokenValue);
}

GenerateJWT逻辑代码

private string GenerateJWT(UserLoginModel model)
{
    var claims = new List<Claim>
    {
        new Claim(ClaimTypes.NameIdentifier, model.Id.ToString()),
        new Claim(JwtRegisteredClaimNames.GivenName, model.FirstName),
        new Claim(JwtRegisteredClaimNames.FamilyName, model.LastName),
        new Claim(JwtRegisteredClaimNames.Email, model.Email),
        new Claim("language", "english"),
    };

    if (model.DateOfBirth.HasValue)
    {
        claims.Add(new Claim(JwtRegisteredClaimNames.Birthdate, model.DateOfBirth.Value.ToShortDateString()));
    }

    var identityClaims = new ClaimsIdentity();
    identityClaims.AddClaims(claims);

    var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["PrivateKey"]));
    var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature);
    var expire = DateTime.UtcNow.AddHours(Convert.ToDouble(configuration["ExpirationHours"]));
    var tokenHandler = new JwtSecurityTokenHandler();

    var tokenDescription = new SecurityTokenDescriptor
    {
        Subject = identityClaims,
        Expires = expire,
        SigningCredentials = credentials,
        Issuer = configuration["Issuer"],
        Audience = configuration["Audience"]
    };
    var token = tokenHandler.CreateToken(tokenDescription);

    return tokenHandler.WriteToken(token);
}

GetCurrentUser接口代码

[HttpGet("current")]
[Authorize] // Add authorization attribute to ensure only authenticated users can access this endpoint
public async Task<IActionResult> GetCurrentUser()
{
   // Retrieve the authenticated user's information from the JWT token's claims
    var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    var firstName = User.FindFirst(JwtRegisteredClaimNames.GivenName)?.Value;
    var lastName = User.FindFirst(JwtRegisteredClaimNames.FamilyName)?.Value;
    var email = User.FindFirst(JwtRegisteredClaimNames.Email)?.Value;
    var dateOfBirth = User.FindFirst(JwtRegisteredClaimNames.Birthdate)?.Value;

    var token = Request.Headers["Authorization"].ToString().Replace("Bearer ", "");


    // Create a response object with the user information
    var currentUser = new CurrentUserModel
    {
        Id = int.Parse(userId),
        FirstName = firstName,
        LastName = lastName,
        Email = email,
        DateOfBirth = !string.IsNullOrEmpty(dateOfBirth) ? DateTime.Parse(dateOfBirth) : null
    };

    logger.LogInformation($"JWT Token: {token}");

    return Ok(currentUser);
}

可能的问题及解决方法

  1. JWT认证配置未正确映射声明
    ASP.NET Core默认不会自动将JwtRegisteredClaimNames下的声明映射到User对象的Claims集合。需要在Startup/Program.cs的认证配置中添加声明映射逻辑:

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
        .AddJwtBearer(options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidateAudience = true,
                ValidateLifetime = true,
                ValidateIssuerSigningKey = true,
                ValidIssuer = configuration["Issuer"],
                ValidAudience = configuration["Audience"],
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["PrivateKey"])),
                SaveSigninToken = true
            };
    
            options.Events = new JwtBearerEvents
            {
                OnTokenValidated = context =>
                {
                    var claimsIdentity = context.Principal.Identity as ClaimsIdentity;
                    if (claimsIdentity != null)
                    {
                        // 将JWT中所有声明添加到Identity
                        foreach (var claim in context.SecurityToken.Claims)
                        {
                            if (!claimsIdentity.HasClaim(c => c.Type == claim.Type))
                            {
                                claimsIdentity.AddClaim(claim);
                            }
                        }
                    }
                    return Task.CompletedTask;
                }
            };
        });
    
  2. 声明类型不匹配
    JwtRegisteredClaimNames.GivenName对应的字符串是"given_name",而ClaimTypes.GivenName是"http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname",两者类型不同。你生成Token时用的是前者,但获取时如果配置默认映射了后者,就会找不到值。

    • 解决方法1:获取声明时直接用字符串类型,比如User.FindFirst("given_name")
    • 解决方法2:生成Token时改用ClaimTypes对应类型:
      var claims = new List<Claim>
      {
          new Claim(ClaimTypes.NameIdentifier, model.Id.ToString()),
          new Claim(ClaimTypes.GivenName, model.FirstName),
          new Claim(ClaimTypes.Surname, model.LastName),
          new Claim(ClaimTypes.Email, model.Email),
          new Claim("language", "english"),
      };
      
  3. Token验证参数不一致
    确保TokenValidationParameters中的ValidIssuer、ValidAudience、IssuerSigningKey和生成Token时的配置完全一致,否则Token会被部分验证,导致声明无法解析。

  4. 前端请求Token完整性
    检查前端调用GetCurrentUser接口时,是否正确将完整Token放在Authorization头中(格式为Bearer {token}),可通过后端日志打印的token值再次解码验证。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 22:05:20