Подключение к концентратору SignalR с консоли с помощью ClaimsPrincial

#c# #signalr #signalr.client

#c# #signalr #signalr.client

Вопрос:

У меня есть очень простой концентратор SignalR, который запущен и работает на моем сервере. Используя пример из Micorsoft, я создал хранилище в памяти для сопоставления пользователей из ClaimsPrincipal в словарь в памяти. Вот код:

  public class NotificationHub : Hub
{
    private readonly static ConnectionMapping<string> _connections = new ConnectionMapping<string>();
    
    public void SendNotification(string who, NotificationData message)
    {
        string name = Context.User.Identity.Name;
        foreach(var connectionId in _connections.GetConnections(who))
        {
            Clients.Client(connectionId).SendAsync("Notification", message);
        }
    }

    public override Task OnConnectedAsync()
    {
        
        string name = Context.UserIdentifier;
        _connections.Add(name, Context.ConnectionId);
        return base.OnConnectedAsync();
    }

    public override Task OnDisconnectedAsync(System.Exception exception)
    {
        string name = Context.User.Identity.Name;
        _connections.Remove(name, Context.ConnectionId);
        return base.OnDisconnectedAsync(exception);
    }
}
 

Я хочу протестировать это с помощью консольного приложения, но я не могу узнать, как создать ClaimsPrincipal в консольном приложении .net core. Вот мой код консольного приложения:

 class Program
{
    static async Task Main(string[] args)
    {

        AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal)
        Console.WriteLine("Press a key to start listening");
        Console.ReadKey();

        Console.WriteLine("Client Listening!");
        var connection = new HubConnectionBuilder()
           .WithUrl("https://localhost:44375/Notify")
           .WithAutomaticReconnect(new[] { TimeSpan.Zero, TimeSpan.Zero, TimeSpan.FromSeconds(10) })
          //.ConfigureLogging(logging =>
          //{
          //    logging.AddConsole();
          //    logging.SetMinimumLevel(LogLevel.Debug);
          //})
           .Build();




        connection.On<NotificationData>("Notification", (notificationData) =>
            Console.WriteLine($"Somebody connected: {notificationData.ClientId}"));

        connection.StartAsync().GetAwaiter().GetResult();
      
        while(Console.ReadKey().Key == ConsoleKey.S)
        {
            var msg = new NotificationData { ClientId = Guid.NewGuid().ToString(), Notifications = null };
            await connection.SendAsync("SendNotification", msg);
            
        }

        
        Console.WriteLine("Listening. Press a key to quit");
        Console.ReadKey();

        connection.Reconnecting  = error =>
        {
            Console.WriteLine("Reconnecting...");
            return Task.CompletedTask;
        };
    }
}
 

Я пытался использовать WindowsPrincipal, но не удалось отправить имя. По-видимому, SignalR должен иметь принципал утверждений. Как отправить claimsprincial из консольного приложения?

Ответ №1:

Я смог создать объект QueryBuilder для перехвата идентификатора пользователя из опубликованного документа JSON и создания строки URI с добавлением элементов QueryBuilder. Затем в методе OnConnectedAsync концентратора я использовал метод Context.GetHttpContext для извлечения пользователя из строки запроса и добавления его в группу. Затем я сопоставляю его со словарем в памяти, чтобы сопоставить идентификатор пользователя с контекстом.Идентификатор подключения.