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
相关产品推荐
相关产品推荐

