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

退出登录后中止SignalR连接的实现方案

实现退出登录时中止用户所有SignalR连接

要实现退出时中止用户的所有SignalR连接,你需要先跟踪用户与连接ID的映射关系,再通过连接ID逐个中止连接。SignalR本身没有直接通过用户ID批量中止连接的API,所以需要自定义连接跟踪逻辑,具体步骤如下:

1. 创建连接跟踪服务

实现一个单例服务,用来存储用户ID和对应连接ID的集合:

using System.Collections.Concurrent;
using System.Collections.Generic;

public class ConnectionTrackingService
{
    // 键:用户ID(ClaimTypes.NameIdentifier的值),值:该用户的所有连接ID集合
    private readonly ConcurrentDictionary<string, HashSet<string>> _userConnections = new();

    // 添加用户连接
    public void AddConnection(string userId, string connectionId)
    {
        _userConnections.AddOrUpdate(userId, 
            _ => new HashSet<string> { connectionId },
            (_, connections) =>
            {
                connections.Add(connectionId);
                return connections;
            });
    }

    // 移除用户连接
    public void RemoveConnection(string userId, string connectionId)
    {
        if (_userConnections.TryGetValue(userId, out var connections))
        {
            connections.Remove(connectionId);
            // 如果用户没有剩余连接,清理条目
            if (connections.Count == 0)
            {
                _userConnections.TryRemove(userId, out _);
            }
        }
    }

    // 获取用户的所有连接ID
    public IEnumerable<string> GetUserConnections(string userId)
    {
        _userConnections.TryGetValue(userId, out var connections);
        return connections ?? Enumerable.Empty<string>();
    }
}

2. 注册连接跟踪服务

在Program.cs(或Startup.cs)中将该服务注册为单例:

builder.Services.AddSingleton<ConnectionTrackingService>();

3. 修改SignalR Hub跟踪连接

在你的TestHub中注入连接跟踪服务,重写连接/断开方法来维护映射关系:

using Microsoft.AspNetCore.SignalR;
using System.Security.Claims;

public class TestHub : Hub
{
    private readonly ConnectionTrackingService _connectionTrackingService;

    public TestHub(ConnectionTrackingService connectionTrackingService)
    {
        _connectionTrackingService = connectionTrackingService;
    }

    public override async Task OnConnectedAsync()
    {
        var userId = Context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (!string.IsNullOrEmpty(userId))
        {
            _connectionTrackingService.AddConnection(userId, Context.ConnectionId);
        }
        await base.OnConnectedAsync();
    }

    public override async Task OnDisconnectedAsync(Exception? exception)
    {
        var userId = Context.User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
        if (!string.IsNullOrEmpty(userId))
        {
            _connectionTrackingService.RemoveConnection(userId, Context.ConnectionId);
        }
        await base.OnDisconnectedAsync(exception);
    }
}

4. 修改AuthController的SignOutAsync方法

注入ConnectionTrackingService,在发送退出通知后,遍历用户的所有连接ID并调用中止方法:

using Microsoft.AspNetCore.SignalR;
using System.Security.Claims;

[Route("api/[controller]")]
[ApiController]
public class AuthController : ControllerBase
{
    // ... 其他代码保持不变 ...

    [HttpDelete("SignOut")]
    [Authorize]
    public async Task SignOutAsync(IHubContext<Hubs.TestHub> hubContext, ConnectionTrackingService connectionTrackingService)
    {
        if (hubContext != null)
        {
            var nameIdentifier = User?.FindFirst(ClaimTypes.NameIdentifier)?.Value;
            if (!string.IsNullOrWhiteSpace(nameIdentifier))
            {
                await hubContext.Clients.User(nameIdentifier).SendAsync("TestHubNotify", $"Sign Out: {nameIdentifier}!");

                // 中止该用户的所有SignalR连接
                var connectionIds = connectionTrackingService.GetUserConnections(nameIdentifier);
                foreach (var connectionId in connectionIds)
                {
                    await hubContext.AbortConnectionAsync(connectionId);
                }
            }
        }

        await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
    }
}

关键说明

  • AbortConnectionAsync是SignalR提供的扩展方法,需要引用using Microsoft.AspNetCore.SignalR;命名空间。
  • 服务器端主动中止连接比仅通知客户端更可靠,能确保用户所有连接立即断开,避免客户端忽略通知的情况。
  • 连接跟踪服务使用ConcurrentDictionary确保多线程环境下的线程安全,适合SignalR的并发连接场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 04:07:11