我正在使用带有Asp.Net核心2.0的SignalR,我正在尝试为这样的特定用户发送通知:
_notification.Clients.User(id).InvokeAsync("SendMes");
其中_notification是IHubContext。 但它不起作用。当我发送所有用户的通知时,一切都很好,所有用户都会收到通知。但是当我将它发送给特定用户时,没有任何反应。在连接中我需要用户,但好像他没有userId。那我该怎么做呢?通过访问身份和声明?如果是这样怎么做?
答案 0 :(得分:2)
问题是我创建了与cookies一起使用的ClaimsIdentity对象:
workspace.onDidOpenTextDocument((doc: TextDocument) => {
if (doc.languageId == "mp3" && doc.uri.scheme === "file") {
// do something
}
});
DefaultNameClaimType是我的电子邮件。当我更改了'ClaimIdentity.DefaultNameClaimType'到'ClaimsTypes.NameIdentifier'这是我的用户ID,所有这些代码都正常工作:
new ClaimsIdentity(claims, "ApplicationCookie", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);
答案 1 :(得分:2)
我遇到了类似的问题,下面的文章帮助我弄清楚了:https://docs.microsoft.com/en-us/aspnet/core/signalr/groups?view=aspnetcore-2.1
在集线器(服务器端)中,我检查了Context.UserIdentifier,即使用户已通过身份验证,它也为null。事实证明, SignalR依赖于ClaimTypes.NameIdentifier ,而我只设置了ClaimTypes.Name。因此,基本上,我添加了另一个声明,然后得出结论(此后,Context.UserIdentifier设置正确)。
下面我分享了部分身份验证代码,以防万一它有用:
var claims = userRoles.Split(',', ';').Select(p => new Claim(ClaimTypes.Role, p.Trim())).ToList();
claims.Insert(0, new Claim(ClaimTypes.Name, userName));
claims.Insert(1, new Claim(ClaimTypes.NameIdentifier, userName)); // this is the claim type that is used by SignalR
var userIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
ClaimsPrincipal principal = new ClaimsPrincipal(userIdentity);
请注意, SignalR用户和组区分大小写。
答案 2 :(得分:0)
用户ID提供程序默认使用IPrincipal.Identity.Name
,对于大多数身份部署,最终都是电子邮件地址。在较旧的SignalR中,可以使用您自己的提供商来定制。
您只需实现以下界面:
public interface IUserIdProvider
{
string GetUserId(IRequest request);
}
然后通过以下方式附上:
GlobalHost.DependencyResolver.Register(typeof(IUserIdProvider), () => new MyIdProvider());
我不确定Core版本中有多少变化。 IUserIdProvider
仍然存在,但界面略有改变:
public interface IUserIdProvider
{
string GetUserId(HubConnectionContext connection);
}
当您在AddSignalR
中致电ConfigureServices
时,它会设置以下内容,当然还有其他内容:
services.AddSingleton(typeof(IUserIdProvider), typeof(DefaultUserIdProvider));
DefaultUserIdProvider
显然是默认实现。似乎没有任何配置选项可以覆盖它,因此如果您需要使用自己的提供程序,则必须替换服务描述符:
services.Replace(ServiceDescriptor.Singleton(typeof(IUserIdProvider),
typeof(MyCustomUserIdProvider)));
显然,这需要在致电AddSignalR
之后。另外,请注意在配置SignalR之前必须先配置auth。否则,用户将无法访问集线器。
答案 3 :(得分:0)
作为@Chris提供的答案的附录。实际上,使用DefaultUserIdProvider
方法添加了IUserIdProvider
的{{1}}实现。
TryAdd*()
因此,您要做的就是在调用services.TryAddSingleton(typeof(IUserIdProvider), typeof(DefaultUserIdProvider));
之前添加您自己的IUserIdProvider
的自定义实现,SignalR会在看到您自己的内容时跳过添加它自己的内容。
services.AddSignalR()
答案 4 :(得分:0)
如果使用JWT,则必须在SecurityTokenDescriptor中添加NameIdentifier声明:
new Claim(ClaimTypes.NameIdentifier, userId)