Blazor Server中如何列出所有会话并查询活跃用户列表
枚举活跃Blazor会话实现活跃用户列表方案
核心实现逻辑
Blazor Server 每个客户端连接会创建独立的依赖注入作用域,IAuthenticationStateProvider 属于作用域服务,我们可以通过「单例会话管理服务+电路生命周期监听」的方式实现活跃会话追踪,全程不需要依赖HTTP会话。
具体实现步骤
- 第一步:定义活跃会话存储实体
public class ActiveBlazorSession { public string SessionId { get; set; } = Guid.NewGuid().ToString(); public ClaimsPrincipal User { get; set; } public DateTimeOffset ConnectedAt { get; set; } = DateTimeOffset.UtcNow; // 可自定义扩展客户端IP、当前访问页面等字段 }
- 第二步:创建单例会话管理服务
public class BlazorSessionManager { // 线程安全字典避免并发操作异常 private readonly ConcurrentDictionary<string, ActiveBlazorSession> _activeSessions = new(); public void AddSession(string sessionId, ActiveBlazorSession session) { _activeSessions.TryAdd(sessionId, session); } public void RemoveSession(string sessionId) { _activeSessions.TryRemove(sessionId, out _); } // 对外提供查询活跃会话的方法 public IEnumerable<ActiveBlazorSession> GetActiveSessions() { return _activeSessions.Values.ToList(); } }
在Program.cs中注册为全局单例:builder.Services.AddSingleton<BlazorSessionManager>();
- 第三步:通过CircuitHandler监听Blazor连接生命周期
Blazor Server的每个长连接对应一个Circuit(电路),通过CircuitHandler可以精准监听到连接的创建、断开事件,比组件生命周期监听更可靠:
public class SessionTrackingCircuitHandler : CircuitHandler { private readonly BlazorSessionManager _sessionManager; private readonly IAuthenticationStateProvider _authStateProvider; private string _currentSessionId; public SessionTrackingCircuitHandler(BlazorSessionManager sessionManager, IAuthenticationStateProvider authStateProvider) { _sessionManager = sessionManager; _authStateProvider = authStateProvider; } public override async Task OnCircuitOpenedAsync(Circuit circuit, CancellationToken cancellationToken) { var authState = await _authStateProvider.GetAuthenticationStateAsync(); // 只记录已登录的用户会话,未登录可按需调整逻辑 if (authState.User.Identity?.IsAuthenticated == true) { _currentSessionId = circuit.Id; var session = new ActiveBlazorSession { SessionId = circuit.Id, User = authState.User }; _sessionManager.AddSession(_currentSessionId, session); } await base.OnCircuitOpenedAsync(circuit, cancellationToken); } public override Task OnCircuitClosedAsync(Circuit circuit, CancellationToken cancellationToken) { if (!string.IsNullOrEmpty(_currentSessionId)) { _sessionManager.RemoveSession(_currentSessionId); } return base.OnCircuitClosedAsync(circuit, cancellationToken); } }
在Program.cs中注册为作用域服务:builder.Services.AddScoped<CircuitHandler, SessionTrackingCircuitHandler>();
- 第四步:获取活跃用户列表
在需要展示活跃用户的组件或者服务中注入BlazorSessionManager,调用GetActiveSessions()方法即可获取所有活跃会话,可通过User对象的声明获取用户名、用户ID等信息,多标签页登录的同个用户可以通过用户ID去重得到唯一活跃用户列表。
注意事项
- 以上方案仅适用于Blazor Server场景,如果是Blazor WebAssembly,需要客户端定时向服务端发送心跳包,服务端维护活跃用户列表,超时自动清理
- Circuit断开事件存在一定的系统延迟,如果需要更精准的在线状态判断,可以额外加心跳逻辑定期更新会话最后活跃时间,清理超过阈值的无效会话
- 对外展示用户信息前需要做脱敏处理,不要暴露ClaimsPrincipal中的敏感字段
内容的提问来源于stack exchange,提问作者Liero
相关产品推荐
相关产品推荐

