SignalR核心中的UserId

时间:2018-01-05 09:25:36

标签: asp.net-core asp.net-core-signalr

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

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

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

5 个答案:

答案 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)
相关问题