SignalR核心中的UserId

问题描述 投票:1回答:4

我正在使用带有Asp.Net核心2.0的SignalR,我正在尝试为特定用户发送通知,如下所示:

_notification.Clients.User(id).InvokeAsync("SendMes");

其中_notification是IHubContext。但它不起作用。当我发送所有用户的通知时,一切都很好,所有用户都会收到通知。但是当我将它发送给特定用户时,没有任何反应。在连接中我需要用户,但好像他没有userId。那我该怎么做呢?通过访问身份和声明?如果是这样怎么办?

asp.net-core asp.net-core-signalr
4个回答
2
投票

问题是我创建了与cookies一起使用的ClaimsIdentity对象,如下所示:

new ClaimsIdentity(claims, "ApplicationCookie", ClaimsIdentity.DefaultNameClaimType, ClaimsIdentity.DefaultRoleClaimType);

DefaultNameClaimType是我的电子邮件。当我将'ClaimsIdentity.DefaultNameClaimType'更改为'claimTypes.NameIdentifier'这是我的用户ID时,所有这些都正常使用此代码:

_notification.Clients.User(id).InvokeAsync("SendMes");

2
投票

我遇到了类似的问题,下面的文章帮助我解决了问题:https://docs.microsoft.com/en-us/aspnet/core/signalr/groups?view=aspnetcore-2.1

在Hub(服务器端)中,我检查了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用户和组区分大小写。


0
投票

用户标识提供程序默认使用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。否则,用户将无法访问集线器。


0
投票

作为@Chris提供的答案的附录。 DefaultUserIdProviderIUserIdProvider实现实际上是使用TryAdd*()方法添加的。

services.TryAddSingleton(typeof(IUserIdProvider), typeof(DefaultUserIdProvider));

因此,您需要做的就是在调用IUserIdProvider之前添加自己的services.AddSignalR()自定义实现,而SignalR会在看到你自己的时候跳过添加它自己。

services.AddSingleton<Microsoft.AspNetCore.SignalR.IUserIdProvider, MyCustomUserIdProvider>();
services.AddSignalR();
© www.soinside.com 2019 - 2024. All rights reserved.