如何在ASP.NET MVC 5中基于Session获取所有实时登录用户及身份信息
关于ASP.NET MVC 5通过Session查询已登录用户的解答
默认情况下你无法直接通过.NET内置的Session接口实时获取所有已登录用户,因为ASP.NET没有对外开放全局的Session枚举API,每个用户的Session是相互隔离存储的,默认不会提供全局访问入口。
可行实现方案
方案1:自定义全局登录状态存储(最常用、改造成本最低)
你可以自己维护一个全局的线程安全存储结构,同步记录所有登录用户的状态:- 登录成功写入Session的同时,把用户身份信息、SessionID、最后活跃时间写入存储
- 每次用户发起请求时更新对应记录的最后活跃时间
- 后台定期清理超过Session超时时长(默认20分钟)无活跃的记录,用户主动登出时直接删除对应记录
单实例部署的场景下可以直接用ConcurrentDictionary做内存存储,多实例部署或者用了分布式Session的场景下,需要把存储换成Redis、数据库这类共享存储。
方案2:自定义Session存储模块
如果你不想修改现有业务登录代码,可以自定义实现SessionStateStoreProvider,在Session创建、过期、销毁的生命周期节点同步更新全局登录用户列表,这种方案改造成本稍高,适合不想侵入业务代码的场景。
注意事项
- 统计的登录状态无法做到100%绝对实时:用户直接关闭浏览器不会主动通知服务端,对应的记录要等到Session超时之后才会被清理,最多会有一个Session超时周期的偏差。
- 如果你的应用是多实例部署,不要用单服务器内存存储登录用户列表,否则会出现数据不一致的问题。
单实例场景示例代码
首先定义用户信息类和全局管理类:
// 登录用户信息实体 public class LoginUser { public string UserId { get; set; } public string UserName { get; set; } public DateTime LastActiveTime { get; set; } } // 全局登录用户管理类 public static class LoginUserCache { // 线程安全字典,Key为SessionID,Value为用户信息 public static readonly ConcurrentDictionary<string, LoginUser> ActiveUsers = new ConcurrentDictionary<string, LoginUser>(); }
登录成功时写入缓存:
// 账号密码验证通过后 Session["UserId"] = loginUser.Id; Session["UserName"] = loginUser.UserName; // 同步写入全局缓存 LoginUserCache.ActiveUsers.AddOrUpdate( Session.SessionID, new LoginUser { UserId = loginUser.Id, UserName = loginUser.UserName, LastActiveTime = DateTime.Now }, (sessionId, oldUser) => { oldUser.LastActiveTime = DateTime.Now; return oldUser; });
添加全局过滤器更新用户活跃时间:
public class ActiveTimeUpdateFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { var session = filterContext.HttpContext.Session; // 仅处理已登录用户的请求 if (session?["UserId"] != null && LoginUserCache.ActiveUsers.TryGetValue(session.SessionID, out var user)) { user.LastActiveTime = DateTime.Now; } base.OnActionExecuting(filterContext); } } // 在Global.asax中注册全局过滤器 GlobalFilters.Filters.Add(new ActiveTimeUpdateFilter());
用户登出时移除缓存:
// 登出逻辑 LoginUserCache.ActiveUsers.TryRemove(Session.SessionID, out _); Session.Abandon();
内容的提问来源于stack exchange,提问作者user1177785
相关产品推荐
相关产品推荐

