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

如何基于Entra用户ID通过SignalR/Azure SignalR推送指定用户通知?

方案可行性与实现思路

一、SignalR通过Entra ID区分用户并推送

你示例中直接用Client(entraUserId)的写法不可行,因为Client()方法仅接受connectionId,但SignalR支持用户标识映射机制,可将Entra用户ID关联到SignalR用户上下文,之后就能直接通过用户ID推送通知,无需手动处理connectionId。

实现步骤:

  • 配置SignalR认证与用户标识提取
    在SignalR服务端(如ASP.NET Core)完成Entra认证配置后,需从认证票据中提取Entra用户的Object ID(对应Claim类型为http://schemas.microsoft.com/identity/claims/objectidentifier,即你提到的GUID格式用户ID),并通过自定义IUserIdProvider将其设置为SignalR的用户ID:
services.AddSignalR()
    .AddAzureSignalR();

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddMicrosoftIdentityWebApi(options =>
    {
        // 配置Entra认证相关选项
    }, options =>
    {
        // 配置Azure AD租户等基础选项
    });

// 注册自定义用户ID提供者
services.AddSingleton<IUserIdProvider, EntraUserIdProvider>();

public class EntraUserIdProvider : IUserIdProvider
{
    public string GetUserId(HubConnectionContext connection)
    {
        // 从用户Claims中提取Entra Object ID
        return connection.User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
    }
}
  • 通过用户ID推送通知
    完成配置后,可使用Users()方法替代Client(),直接针对Entra用户ID列表推送:
foreach(var entraUserId in notification.Users)
{
    await this.hubContext.Users(entraUserId).SendAsync("ReceiveNotification", message);
}

Users()方法会自动匹配所有关联该用户ID的活跃连接,批量推送通知,无需手动维护connectionId与用户ID的映射关系。

二、Entra用户ID与connectionId的手动映射(可选)

如果需要额外管理连接状态,可通过SignalR的连接事件手动维护映射关系:

  • 在Hub类中监听OnConnectedAsync和OnDisconnectedAsync事件,记录用户ID与connectionId的对应关系:
public class NotificationHub : Hub
{
    private static readonly Dictionary<string, List<string>> UserConnectionMap = new();

    public override async Task OnConnectedAsync()
    {
        var userId = Context.User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
        if (!string.IsNullOrEmpty(userId))
        {
            lock (UserConnectionMap)
            {
                if (!UserConnectionMap.ContainsKey(userId))
                {
                    UserConnectionMap[userId] = new List<string>();
                }
                UserConnectionMap[userId].Add(Context.ConnectionId);
            }
        }
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception exception)
    {
        var userId = Context.User.FindFirst("http://schemas.microsoft.com/identity/claims/objectidentifier")?.Value;
        if (!string.IsNullOrEmpty(userId))
        {
            lock (UserConnectionMap)
            {
                if (UserConnectionMap.ContainsKey(userId))
                {
                    UserConnectionMap[userId].Remove(Context.ConnectionId);
                    if (UserConnectionMap[userId].Count == 0)
                    {
                        UserConnectionMap.Remove(userId);
                    }
                }
            }
        }
        await base.OnDisconnectedAsync(exception);
    }
}

之后可通过该字典获取指定Entra用户对应的所有connectionId,再调用Client(connectionId)推送通知。

三、Azure Function + Azure SignalR + Service Bus的场景实现

当Service Bus触发Function App时,完全可以向特定Entra用户ID推送通知,核心是利用Azure SignalR的服务端推送能力与用户标识映射:

实现步骤:

  • 配置Function与Azure SignalR集成
    在Function App中安装Microsoft.Azure.WebJobs.Extensions.SignalRService包,并配置Azure SignalR服务的连接字符串。

  • 关联用户标识
    Angular客户端连接SignalR时需携带Entra认证Token,Azure SignalR会自动解析Token中的用户Claim,你也可在Function中通过自定义逻辑提取Entra Object ID作为用户标识。

  • Service Bus触发的推送逻辑
    在Service Bus触发的Function中,使用SignalRAsyncCollector向指定用户推送通知:

[FunctionName("NotifyUsersFromServiceBus")]
public static async Task Run(
    [ServiceBusTrigger("notification-queue", Connection = "ServiceBusConnection")] string notificationJson,
    [SignalR(HubName = "NotificationHub")] IAsyncCollector<SignalRMessage> signalRMessages,
    ILogger log)
{
    var notification = JsonSerializer.Deserialize<Notification>(notificationJson);
    foreach (var entraUserId in notification.Users)
    {
        await signalRMessages.AddAsync(new SignalRMessage
        {
            UserId = entraUserId,
            Target = "ReceiveNotification",
            Arguments = new[] { notification.Message }
        });
    }
}

这里直接将Entra用户ID传入UserId字段即可,Azure SignalR会自动匹配该用户的所有活跃连接并推送通知。

需注意,Function App需配置Entra认证权限,确保能正确解析客户端Token并关联用户标识。


内容的提问来源于stack exchange,提问作者Ignacio Iron Babbini

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 05:43:21