使用Azure SignalR(不是.Net Core SignalR),是Clients.Users.SendAsync
支持向特定用户发送消息吗?
[Authorize]
public class ChatHub : Hub
{
public async Task OnNewMessage(string userId, string message)
{
await Clients.Users(userId)
//Does Azure SignalR supports sending message to specific user,
// the way .Net Core SignalR does it
.SendAsync("OnNewMessage", userId, message);
}
}
If yes, How Asp.Net Identity Claims Principal gets passed to Azure SignalR?
编辑:2021 年 6 月 18 日
以下回复并未解决您的问题。抱歉,我已经遵循了自定义文档 UserIdBasedProvider
等等。我想强调的是 -
This question is pertaining to how SignalR handles
.Users(<*some-user-id*>).Send()
;
理想情况下我们会这样做
.Client(<connection id>).Send()
向特定用户发送消息。但对于这种架构,我们必须自己将 userId 和 connectionId 存储在数据库等中。
.User(userId).Send()
与.Net Core SignalR 完美配合。所以我相信 SignalR SDK 一定在内存中保存了每个连接 ID 和用户 ID 的映射。
Does Azure SignalR internally keeps track of UserId, Connection Id mapping and sends the message?
最佳答案
是的,如果您想实现无服务器架构,您应该使用 Azure Functions。典型的无服务器架构如下所示
客户端(即浏览器)向 azure 函数发送协商请求,响应包含与 Azure SignalR
建立连接所需的所有信息。您应该将 JWT token 附加到协商请求中。如何获取 JWT token 取决于您。附加它非常简单,只需在创建 signalR 连接时提供一个 token 工厂即可
const connection = new signalR.HubConnectionBuilder()
.withUrl('link to your azure functions api', {
accessTokenFactory: () => {
return 'your token'
}
})
.build();
为此,您还需要设置 upstream连接,以便您的 Azure SignalR
服务可以将所有事件转发到您的 Azure Function。 Azure funciton 处理上游事件并向 Azure SignalR
发送请求,以向给定用户或多个用户广播数据。
集线器
中的SendMessage
方法的代码与常规集线器非常相似,除了Azure函数绑定(bind)之外。您还需要扩展 ServerlessHub
类而不是 Hub
并安装 Microsoft.Azure.WebJobs.Extensions.SignalRService
包
public class ChatHub : ServerlessHub
{
[FunctionName(nameof(SendToUser))]
public async Task SendToUser([SignalRTrigger] InvocationContext invocationContext, string userName, string message)
{
await Clients.User(userName).SendAsync("new_message", new NewMessage(invocationContext, message));
}
[FunctionName("negotiate")]
public SignalRConnectionInfo Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequest req)
{
var claims = GetClaims(req.Headers["Authorization"]);
var userName = claims.First(x => x.Type == ClaimTypes.NameIdentifier);
return Negotiate(userName.Value, claims);
}
private class NewMessage
{
public string ConnectionId { get; }
public string Sender { get; }
public string Text { get; }
public NewMessage(InvocationContext invocationContext, string message)
{
Sender = string.IsNullOrEmpty(invocationContext.UserId) ? string.Empty : invocationContext.UserId;
ConnectionId = invocationContext.ConnectionId;
Text = message;
}
}
}
您还可以找到包含分步说明的代码示例 here
编辑:
如果您不想完全无服务器并且想使用常规网络应用程序,那也完全没问题。架构图如下所示
在这种情况下,您应该使用常规的集线器类。您发布的代码应该可以正常工作。
连接管理完全由 Azure Signalr 服务完成,您不需要执行任何额外的同步,也不需要将连接数据存储在数据库中。只需设置层大小和单位数量即可。
以下是其工作原理的简短描述:
- 客户端(例如浏览器中的 Js 客户端)将请求发送到 Web 应用程序的
negotiate
端点,并接收指向 azure signalr 服务的链接和访问 token 。这是一个 JWT token 。 JWT token 由几个部分组成。该 token 的第二部分是有效负载,其中包含声明。 - 使用从
negotiate
端点客户端获取的数据连接到 azure signalr 服务。
因此,Azure SignalR 服务使用从协商端点接收的此访问 token 来对用户进行身份验证。您不必编写任何额外的代码,因为这一切都是由库在幕后完成的。
如果您使用网络应用,negotiate
请求由 SignalR Sdk 处理,您无需为此编写任何额外代码。
这一切都在this article中有描述。
您可以找到有关实现身份验证的详细指南 here
关于c# - 使用 Azure SignalR 向特定用户发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67903234/