使用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"])) }; });
排查与解决方案
修复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 }验证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" };
- 改用JWT标准声明存储用户ID:
确认中间件顺序正确
在Program.cs中,UseAuthentication必须在UseAuthorization之前执行,否则认证信息无法被正确加载:app.UseAuthentication(); app.UseAuthorization();检查Token内容
手动解码生成的Token,确认Payload中是否包含对应的用户ID声明。如果声明不存在,说明Token生成过程存在问题;如果存在但无法获取,需检查中间件配置是否正确解析声明。
内容的提问来源于stack exchange,提问作者prajwal lama
相关产品推荐
相关产品推荐

