Как осуществить Аутенфикацию и Авторизацию пользователя на декстоп приложении для signalR?

Рейтинг: 0Ответов: 0Опубликовано: 03.08.2023

Как реализовать авторизацию пользователя для декстоп приложения на signalR? Существует форма логина, которая состоит из пароля и логина. Нужно отправить логин и пароль и получить данные пользователя и авторизоваться на вебе signalR. Я не силен в вебе в принципе и пытаюсь найти информацию по этому поводу, но пока что слишком много вопросов. Хочется понять, как происходит сам процесс аутенфикации и авторизации с помощью токенов.

В кратце о ВЕБ проекте, есть хаб менеджер который контролирует пользователей при входы и выходе. Контекст с базой рабочий.

Декстоп пишу на WPF. В принципе это не важно.

Везде использую .NET 6.0

Прилагаю структуру SignalR решения:

введите сюда описание изображения

ChatHub:

public class ChatHub : Hub<IChatHub>
    {
        public ChatHub(ChatHubManager hubManager) => _chatHubManager = hubManager;
        
        private readonly ChatHubManager _chatHubManager;
        
        private const string DefaultGroupName = "KPPGROUP";

        #region Overrides

        public override async Task OnConnectedAsync()
        {
            _chatHubManager.ConnectUser(Guid.NewGuid().ToString(), Context.ConnectionId);

            await Groups.AddToGroupAsync(Context.ConnectionId, DefaultGroupName);
            await UpdateUsersAsync();
            await base.OnConnectedAsync();
        }

        public override async Task OnDisconnectedAsync(Exception? exception)
        {
            if(_chatHubManager.DisconnectUser(Context.ConnectionId)) await base.OnDisconnectedAsync(exception);

            await Groups.RemoveFromGroupAsync(Context.ConnectionId, DefaultGroupName);
            await UpdateUsersAsync();
            await base.OnDisconnectedAsync(exception);
        }

        #endregion

        [Authorize]
        public async Task UpdateUsersAsync()
        {
            var users = _chatHubManager.ConnectedUsers.Select(x => x.Id).ToList();
            await Clients.All.UpdateUsersAsync(users);
        }

        [Authorize]
        public async Task SendPrivateMessageAsync(string senderId, string recipientId, byte[] message) =>
            await Clients.All.SendPrivateMessageAsync(senderId, recipientId, message);
    }

public interface IChatHub
   {
       public Task UpdateUsersAsync(IEnumerable<string> users);
       public Task SendPrivateMessageAsync(string senderId, string recipientId, byte[] message);
    }

UserConnection:

public class UserConnection
    {
        public UserConnection(string id)
        {
            Id = id;
            _connections = new();
        }

        public string Id { get; set; }

        public DateTime ConnectedAt
        {
            get
            {
                if (Connections.Any())
                {
                    return Connections
                        .OrderByDescending(x => x.ConnectedAt)
                        .Select(x => x.ConnectedAt)
                        .First();
                }

                return new DateTime();
            }
        }

        private readonly List<ChatConnection> _connections;
        public IEnumerable<ChatConnection> Connections => _connections;

        public void AppendConnection(string connectionId)
        {
            if (string.IsNullOrEmpty(connectionId)) throw new ArgumentNullException(nameof(connectionId));

            _connections.Add(new()
            {
                ConnectionId = connectionId,
                ConnectedAt = DateTime.Now,
            });
        }
        public void RemoveConnection(string connectionId)
        {
            if (string.IsNullOrEmpty(connectionId)) throw new ArgumentNullException(nameof(connectionId));

            var connection = _connections.FirstOrDefault(x => x.ConnectionId == connectionId);

            if (connection == null) return;

            _connections.Remove(connection);
        }
    }

ChatHubManager:

public class ChatHubManager
    {
        public List<UserConnection> ConnectedUsers { get; set; } = new();

        public bool ConnectUser(string userId, string connectionId)
        {
            try
            {
                var existsUser = GetConnectedUserById(userId);
                if (existsUser != null)
                {
                    existsUser.AppendConnection(connectionId);
                    return true;
                }

                UserConnection user = new(userId);
                user.AppendConnection(connectionId);
                ConnectedUsers.Add(user);
                return true;
            }
            catch (Exception ex) { return false; }
        }

        public bool DisconnectUser(string connectionId)
        {
            try
            {
                var user = GetConnectedUserByConnectionId(connectionId);

                if (user == null) return true;

                if (user.Connections.Count() == 1)
                {
                    user.RemoveConnection(user.Connections.Last().ConnectionId);
                    ConnectedUsers.Remove(user);
                    return true;
                }

                if (!user.Connections.Any())
                {
                    ConnectedUsers.Remove(user);
                    return true;
                }

                user.RemoveConnection(user.Connections.Last().ConnectionId);
                
                return true;
            }
            catch(Exception ex)
            {
                return false;
            }
        }

        private UserConnection? GetConnectedUserById(string userId) =>
            ConnectedUsers.FirstOrDefault(x => x.Id == userId);

        private UserConnection? GetConnectedUserByConnectionId(string connectionId) =>
            ConnectedUsers.FirstOrDefault(x => x.Connections.Select(c => c.ConnectionId).Contains(connectionId));
    }

ChatConnection:

public class ChatConnection
    {
        public DateTime ConnectedAt { get; set; }

        public string ConnectionId { get; set; } = null!;
    }

Program.cs:

using JurChat.Server.Hubs;
using JurChat.Server.Hubs.Infrastructure;
using JurChat.Server.Persistence;

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddSignalR();
builder.Services.AddControllers();
builder.Services.AddDbContext<ApplicationDbContext>();
builder.Services.AddSingleton<ChatHubManager>();

var app = builder.Build();

app.UseDefaultFiles();
app.UseStaticFiles();
app.UseRouting();

app.MapHub<ChatHub>("/chat");

app.Run();

Ответы

Ответов пока нет.