You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Azure隔离函数中SignalR向特定用户/组发消息的问题

问题:Azure隔离函数中如何向特定用户/组发送SignalR消息

技术栈

  • 后端:.NET 6, C#10, Azure 隔离函数项目
  • NuGet包:Microsoft.Azure.Functions.Worker.Extensions.SignalRService v1.7.0
  • 前端:Angular, TypeScript, MSAL (@azure/msal-angular": "^2.3.0"), SignalR (@microsoft/signalr": "^7.0.5")

当前实现与问题

我需要实现向特定用户或组发送SignalR消息的功能,发现通过给SignalRConnectionInfoInput.UserId赋值可以达成目标,但该类是密封类,找不到动态设置UserId的方法。

已实现的广播功能

获取连接信息的Negotiate函数

[Function(nameof(Negotiate))]
public static HttpResponseData Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "MyHubName")] string connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "application/json");
    response.WriteString(connectionInfo);
    return response;
}

向所有用户广播消息的函数

[Function(nameof(BroadcastToAll))]
public static SignalRMessageAction BroadcastToAll([HttpTrigger(AuthorizationLevel.Anonymous,   
   "post", Route = nameof(BroadcastToAll))] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    var body = bodyReader.ReadToEnd();
    return new SignalRMessageAction("MyTargetName")
    {
        Arguments = new object[] { body },
    };
}

硬编码UserId的可行方案

只有在Negotiate函数中硬指定UserId时,才能正常向特定用户发消息。此时Azure SignalR Service返回的connectionInfo里的accessToken会包含"asrs.s.uid": "12345"的用户标识声明:

[Function(nameof(Negotiate))]
public static HttpResponseData Negotiate([HttpTrigger(AuthorizationLevel.Anonymous)] HttpRequestData req,
    [SignalRConnectionInfoInput(HubName = "MyHubName", UserId = "12345")] string connectionInfo)
{
    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "application/json");
    response.WriteString(connectionInfo);
    return response;
}

之后可以通过SignalRMessageAction的UserId属性指定接收消息的用户:

[Function(nameof(SendToUser))]
public static async Task<SignalRMessageAction> SendToUser(
    [HttpTrigger(AuthorizationLevel.Anonymous, "post", 
        Route = nameof(SendToUser))] HttpRequestData req)
{
    using var bodyReader = new StreamReader(req.Body);
    var requestBody = await bodyReader.ReadToEndAsync();
    return new SignalRMessageAction("MyTargetName")
    {
        Arguments = new object[] { requestBody },
        UserId = "12345"
    };
}

前端连接代码示例

public ConnectSignalR(): void {
    this.hubConnection = new signalR.HubConnectionBuilder().withUrl(this.basePath).build();
    
    this.hubConnection
    .start()
    .then(() => console.log('Connection started'))
    .catch((err) => console.log('Error while starting connection: ' + err));
    
    this.hubConnection.on('MyTargetName', (mySignalRMessage: string) => {
        console.log(mySignalRMessage)
    });
}

public DisconnectSignalR(): void {
    if (this.hubConnection) {
      this.hubConnection.stop();
    }
}

待解决的问题

我曾尝试按照官方文档中“已验证令牌”的方案,设置UserId = "{headers.x-ms-client-principal-id}",但由于使用MSAL认证,请求中不存在该请求头。现在希望能在后端自行动态设置UserId值,从而实现向特定用户发送消息的功能。

内容的提问来源于stack exchange,提问作者Lekster001

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 16:55:39