SignalR中Context.User.Identity.Name始终返回null的问题排查
问题原因及解决方案
核心问题
Context.User.Identity.Name 对应的是 ClaimTypes.Name 类型的JWT声明,但你在生成令牌时只添加了 ClaimTypes.NameIdentifier 声明,两者不匹配,导致读取结果为null。
解决方案(二选一即可)
方案1:修改令牌生成逻辑,添加ClaimTypes.Name声明
在Token Service的GetToken方法中,给claims数组新增一行ClaimTypes.Name的声明:
var claims = new[] { new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]), new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()), new Claim("userId", user.Id.ToString()), new Claim(ClaimTypes.NameIdentifier, user.UserName), new Claim(ClaimTypes.Name, user.UserName), // 新增这一行 };
修改后,Context.User.Identity.Name就能正确读取到用户名。
方案2:直接读取ClaimTypes.NameIdentifier的值
如果不想修改令牌生成逻辑,直接在Hub中读取你已经添加的NameIdentifier声明:
public void SendMessageToUser(string name, string message) { var mySelf = Context.User.FindFirstValue(ClaimTypes.NameIdentifier); // 替换原来的读取方式 _hubContext.Clients.Users(mySelf, name).SendAsync("GetMessage", message, name).Wait(); }
这种方式不需要改动令牌,直接读取已存在的声明值。
额外优化(可选)
SignalR的Clients.Users()方法默认使用ClaimTypes.NameIdentifier作为用户标识,如果你希望统一用户ID的解析规则,可以在SignalR微服务的Program.cs中配置自定义UserIdProvider:
builder.Services.AddSignalR(options => { options.UserIdProvider = context => context.User.FindFirstValue(ClaimTypes.NameIdentifier); // 指定用NameIdentifier作为用户ID });
这能避免后续使用Clients.Users()时出现标识不匹配的问题。
内容的提问来源于stack exchange,提问作者Inbar Manor
相关产品推荐
相关产品推荐

