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

如何在EventGrid触发的Azure Function事件中获取User ID

问题

我有一个基于.NET7独立工作进程的EventGrid触发Azure Function,每当客户端连接SignalR hub时会被调用,代码如下:

[Function("v1-on-connectivity-events-changed")]
public async Task OnConnectivityEventsChangedAsync
(
    [EventGridTrigger]
    EventGridConnectivityEvent eventGridConnectivityEvent,
    FunctionContext functionContext
)
{
  _logger.LogWarning("Event grid trigger received. Data='{ConnectionInfo}'", JsonSerializer.Serialize(eventGridConnectivityEvent));
  ...
}

客户端通过Negotiate API连接SignalR的代码如下:

_hubConnection = new HubConnectionBuilder()
                .WithUrl(hubEndpoint.AbsoluteUri, options =>
                {
                    //  Adds the application token to the options' header.
                    options.AccessTokenProvider = () => Task.FromResult(user.IdentityToken.AccessToken)!;
                    options.Headers.Add("userSid", user.IdentityToken.UserSid);   
                })
                .Build();

...

await _hubConnection.StartAsync();

Negotiate函数返回包含额外参数的URL,代码如下:

[Function("negotiate")]
public Task<SignalRConnectionInfo> OnNegotiateAsync
(
    [HttpTrigger(AuthorizationLevel.Anonymous, "POST")]
    HttpRequestData httpRequestData,
    [SignalRConnectionInfoInput
    (
       HubName = Constants.HubName,
       ConnectionStringSetting = "AzureSignalRConnectionString"
    )]
    SignalRConnectionInfo signalRConnectionInfo
)
{
        return ExecuteAsync(httpRequestData, async claimsPrincipal =>
        {
            IUserPrincipal userPrincipal = await RetrieveClaimsAsync(httpRequestData, claimsPrincipal);

            signalRConnectionInfo.Url += $"&userSid={userPrincipal.UserSid}";
            
            return signalRConnectionInfo;
        });
    }

客户端连接时,OnConnectivityEventsChangedAsync函数可正常触发,但事件中缺少所需的User ID。根据SignalR文档,连接事件应同时提供User ID和Connection ID,而当前收到的事件数据如下:

{
    "Id":"56f3ab25-11d7-41d6-acbb-8429a741d746",
"Topic":"/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.SignalRService/SignalR/<signalr_instance>",
    "Subject":"hub/updates",
    "EventType":"Microsoft.SignalRService.ClientConnectionConnected",
    "EventTime":"2022-11-27T19:22:19.2349923Z",
    "Data": { 
         "timestamp":"2022-11-27T19:22:19.2349923Z",
         "hubName":"updates",
         "connectionId":"gmJM_GHVkXsQuS5C1LhdXXXXX"
    }
}

请问如何在事件中同时获取User ID和Connection ID?

解决方案

要让Azure SignalR的Event Grid事件包含User ID,需确保协商阶段正确关联用户标识,而非仅手动拼接URL参数,具体操作如下:

  • 通过SignalRConnectionInfoInput绑定设置用户标识
    修改Negotiate函数的SignalRConnectionInfoInput属性,添加UserId绑定表达式,直接从请求头或令牌声明中获取用户ID。示例中从请求头的userSid字段获取:

    [SignalRConnectionInfoInput
    (
       HubName = Constants.HubName,
       ConnectionStringSetting = "AzureSignalRConnectionString",
       UserId = "{headers.userSid}"
    )]
    SignalRConnectionInfo signalRConnectionInfo
    

    此操作会让Azure SignalR服务自动将用户ID与连接关联,后续连接事件将携带该字段。

  • 移除手动拼接URL的代码
    无需再手动给signalRConnectionInfo.Url追加userSid参数,因为UserId绑定已完成用户标识关联。修改后的Negotiate核心代码如下:

    [Function("negotiate")]
    public Task<SignalRConnectionInfo> OnNegotiateAsync
    (
        [HttpTrigger(AuthorizationLevel.Anonymous, "POST")]
        HttpRequestData httpRequestData,
        [SignalRConnectionInfoInput
        (
           HubName = Constants.HubName,
           ConnectionStringSetting = "AzureSignalRConnectionString",
           UserId = "{headers.userSid}"
        )]
        SignalRConnectionInfo signalRConnectionInfo
    )
    {
            return ExecuteAsync(httpRequestData, async claimsPrincipal =>
            {
                IUserPrincipal userPrincipal = await RetrieveClaimsAsync(httpRequestData, claimsPrincipal);
                return signalRConnectionInfo;
            });
        }
    
  • 验证事件数据
    完成修改后,客户端重新连接,Event Grid触发的事件数据将新增userId字段,示例如下:

    {
        "Id":"56f3ab25-11d7-41d6-acbb-8429a741d746",
    "Topic":"/subscriptions/<subscription_id>/resourceGroups/<resource_group>/providers/Microsoft.SignalRService/SignalR/<signalr_instance>",
        "Subject":"hub/updates",
        "EventType":"Microsoft.SignalRService.ClientConnectionConnected",
        "EventTime":"2022-11-27T19:22:19.2349923Z",
        "Data": { 
             "timestamp":"2022-11-27T19:22:19.2349923Z",
             "hubName":"updates",
             "connectionId":"gmJM_GHVkXsQuS5C1LhdXXXXX",
             "userId":"your-user-sid-value"
        }
    }
    
  • 扩展说明
    如果用户标识来自JWT令牌的声明,可调整UserId的绑定表达式,例如从令牌的特定声明字段获取,确保Azure SignalR服务能正确关联用户ID与连接。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:00:59