【问题标题】:How to send SignalR notifications to specific user in ASP.NET Core (MVC) with Windows Authentication?如何使用 Windows 身份验证向 ASP.NET Core (MVC) 中的特定用户发送 SignalR 通知?
【发布时间】:2021-06-18 16:53:44
【问题描述】:

我正在开发一个 ASP.NET Core MVC Web 应用程序。该应用程序使用 Windows 身份验证。一旦收到发布请求,我想从 API 控制器向客户端发送通知。我发现这个资源https://docs.microsoft.com/en-us/aspnet/core/signalr/authn-and-authz?view=aspnetcore-5.0) 说我需要使用 CustomUserIdProvider 来获取特定用户的 ID。但是,我不确定我应该如何调用以下方法:

_myHub.Clients.User(specificUserId).SendAsync("ReceiveMessage", message);

如何在我的 API 控制器中获取该 specificUserId。我尝试注入 CustomUserIdProvider 然后调用此方法:

_myHub.Clients.User(_customUserIdProvider.GetUserId(conn)).SendAsync("ReceiveMessage", message);

但是我不知道如何从这个 API 控制器获取 GetUserId 方法所需的 HubConnectionContext conn 对象。

这是 CustomUserIdProvider 类:

public class CustomUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        return connection.User?.Identity?.Name;
    }
}

如果这不起作用,是否有任何其他方式可以将 SignalR 通知发送给通过 Windows 身份验证对 ASP.NET MVC Web 应用程序进行身份验证的特定用户?谢谢!

【问题讨论】:

  • 您不存储此 ID(或从传入的帖子请求中获取它们)吗?我的意思是.. 你现在怎么能把这条消息发给谁呢?
  • 我正在考虑在 post 请求中发送 [Domain][Username]。然后,如果我可以获得由 customUserIdProvider 生成的所有连接 Id,我可以将这些用户名映射到它们对应的 connectionId。但是,如何使用 customeUserIdProvider 方法在我的 API 控制器中获取这些连接 ID?

标签: c# asp.net-core asp.net-core-mvc signalr windows-authentication


【解决方案1】:

您不应该将 CustomUserIdProvider 的实例传递给集线器。 IUserIdProvider 定义了 SignalR 如何返回 userId 并识别用户的幕后发生的事情。

您注册了您的 CustomUserIdProvider

services.AddSingleton<IUserIdProvider, CustomUserIdProvider>();

这样做的目的是将您提供的用户 ID 与它在其用户列表中查找的用户 ID 相匹配。

如果您尝试在控制器而不是集线器中执行此操作,我认为您可以这样做:

public Controller(IHttpContextAccessor httpContextAccessor)
{
   _userId = httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value;
}

从这个答案中可以看出:https://stackoverflow.com/a/36641907/2490286

然后

_myHub.Clients.User(_userId).SendAsync("ReceiveMessage", message);

【讨论】:

  • 非常感谢@misha130!它工作得非常好!我只需要将 ClaimTypes.NameIdentifier 更改为 ClaimTypes.Name 因为第一个返回 null。然后我按照@Timur Umerov 的建议在 _myHub.Clients.User(message.username) 方法中将 _userId 更改为 message.username。
【解决方案2】:

您不需要实际的连接。如果您通过 post 请求发送用户名,只需使用该用户名并将其传递到此处

_myHub.Clients.User(Username).SendAsync("ReceiveMessage", message);

或者如果它包含在消息对象中

_myHub.Clients.User(message.Username).SendAsync("ReceiveMessage", message);

更新

如果您在CustomUserIdProvider 中使用connection.User?.Identity?.Name 获得的字符串格式是[Domain][Username],那么您应该可以通过Post 请求传递它,然后在User() 方法中使用它。

【讨论】:

  • 谢谢!您的解决方案有效,但只是在使用 _userId = httpContextAccessor.HttpContext.User.FindFirst(ClaimTypes.NameIdentifier).Value; 生成的映射之后。正如@misha130 所建议的那样。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 2011-07-17
  • 2015-04-17
  • 2017-12-31
  • 1970-01-01
相关资源
最近更新 更多