简体   繁体   中英

How to prevent multiple connection from one JWT claim to one hub [SignalR, C#]

Let's say our application accepts JWT Bearer authorization on SignalR Hub.

Since we have a ban on anonymous connections, then we also have data that can be limited to this, right? The task is to block several connections at the same time from this token to the Hub.

I came up with the idea to make a list of users and add / remove via OnConnected / OnDisconnected, and just reject requests, is this a good idea or are there better options?

If anyone insterested in my implementation, here it is (i think it can be better):

Hub.cs:

    private static readonly ConnectionMapping Connections = new();
    
    public async Task JoinGroup(string group)
    {
        string username = Context.User.Identity.Name;

        Connections.Add(group, username);
        
        await Groups.AddToGroupAsync(Context.ConnectionId, group);
        await Clients.Group(group).SendAsync("UserConnected", Connections.GetConnections(group));
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        string username = Context.User.Identity.Name;
        string group = Connections.GetKey(username);
        
        Connections.Remove(group, username);
        
        await Clients.Group(group).SendAsync("UserConnected", Connections.GetConnections(group));
        
        await base.OnDisconnectedAsync(exception);
    }

ConnectionMapping.cs:

public class ConnectionMapping
{
    private readonly Dictionary<string, List<string>> _groups = new();

    public void Add(string key, string connectionId)
    {
        List<string> connections;
        
        if (!_groups.TryGetValue(key, out connections))
        {
            connections = new List<string>();
            _groups.Add(key, connections);
        }

        connections.Add(connectionId);
    }

    public void Remove(string key, string connectionId)
    {
        List<string> connections;
        
        if (!_groups.TryGetValue(key, out connections))
            return;

        connections.Remove(connectionId);

        if (connections.Count == 0)
            _groups.Remove(key);
    }
    
    public IEnumerable<string> GetConnections(string key)
    {
        List<string> connections;
        
        if (_groups.TryGetValue(key, out connections))
            return connections.Distinct();

        return Enumerable.Empty<string>();
    }

    public string GetKey(string connectionId)
    {
        string key = _groups.FirstOrDefault(x => x.Value.Contains(connectionId)).Key;

        if (!key.IsNullOrEmpty()) 
            return key;
        
        return string.Empty;
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM