2016-04-11 53 views
2

在我的应用程序中,我想检查某个特定用户是否已登录,因此我可以显示一个状态,指出该用户是“在线”或“离线”给另一个用户。这个问题是而不是关于验证用户,只关于获取用户的验证状态。ASP.NET MVC - 获取用户的登录状态

我该如何去实现这一目标?

+0

我不认为有一个内置的可用于这一领域。我建议在'AspNetUsers'表的数据库中创建一个自定义布尔字段。在登录时将其设置为true,并在登出时将其设置为false。 –

+0

@DrewKennedy如果有人没有实际登出,而是关闭了标签页或浏览器,或导航到另一个网站,那么这样做会有用吗? – RoyalSwish

+0

当我提出这个问题时,这是我心中的一个限制。答案是我非常怀疑它。这可能必须由JavaScript来完成,但我无法提供确切的答案。 –

回答

3

我认为一个选择是使用一些实时解决方案。例如,SignalR。 用户登录后,将其连接到集线器。 OnConnected()动作保存其状态。然后OnDisconnected()从“OnlineRepository”中移除。

更新与示例 这是我在asp.Net Mvc 5应用程序中如何做到这一点。

  • 保持像一个单一的用户A模型类:

    
        public class SingleConnection 
        { 
         public SingleConnection() 
         { 
          ConnectionId = new List(); 
         } 
         public string Id { get; set; } 
         public List ConnectionId { get; set; } 
        } 
    
  • 的连接映射类,可以帮助在加法/ removeing和从列表

    
        public class ConnectionMapping 
        { 
         private readonly List _connections = new List(); 
         public int Count 
         { 
          get 
          { 
           return _connections.Count; 
          } 
         } 
         public void Add(string key, string connectionId) 
         { 
          lock (_connections) 
          { 
           var sn = _connections.Where(x => x.Id == key).FirstOrDefault(); 
           if (sn != null) // there is a connection with this key 
           { 
            _connections.Find(x => x.Id == key).ConnectionId.Add(connectionId); 
           } 
           else 
           { 
            _connections.Add(new SingleConnection { Id = key, ConnectionId = new List { connectionId } }); 
           } 
          } 
         } 
         public List GetConnections(string id) 
         { 
          var con = _connections.Find(x => x.Id == id); 
          return con != null ? con.ConnectionId : new List(); 
         } 
         public List AllConnectionIds() 
         { 
          List results = new List(); 
          var allItems = _connections.Where(x => x.ConnectionId.Count > 0).ToList(); 
          foreach (var item in allItems) 
          { 
           results.AddRange(item.ConnectionId); 
          } 
          return results; 
         } 
         public List AllKeys() 
         { 
          return _connections.Select(x => x.Id).ToList(); 
         } 
         public void Remove(string key, string connectionId) 
         { 
          lock (_connections) 
          { 
           var item = _connections.Find(x => x.Id == key); 
           if (_connections.Find(x => x.Id == key) != null) 
           { 
            _connections.Find(x => x.Id == key).ConnectionId.Remove(connectionId); 
            if (_connections.Find(x => x.Id == key).ConnectionId.Count == 0) 
            { 
             _connections.Remove(item); 
            } 
           } 
          } 
         } 
        } 
    
    • 得到一个用户在我的集线器类
    
    private void IsActive(string connection, bool connected) 
    { 
        Clients.All.clientconnected(connection, connected); 
    } 
    public override Task OnConnected() 
    { 
        string name = Context.User.Identity.Name; 
        _connections.Add(name, Context.ConnectionId); 
        IsActive(name, true); 
        return base.OnConnected(); 
    } 
    public override Task OnDisconnected(bool stopCalled) 
    { 
        string name = Context.User.Identity.Name; 
        _connections.Remove(name, Context.ConnectionId); 
        IsActive(name, false); 
        return base.OnDisconnected(stopCalled); 
    } 
    public override Task OnReconnected() 
    { 
        string name = Context.User.Identity.Name; 
        if (!_connections.GetConnections(name).Contains(Context.ConnectionId)) 
        { 
         _connections.Add(name, Context.ConnectionId); 
        } 
        IsActive(name, false); 
        return base.OnReconnected(); 
    } 
    
  • 在_Layout.cshtml

    
    // reference scripts 
    // add a callback or the OnConnected() Will not fire 
    chat.client.clientconnected = function (id,active){ 
    /* 
    this will be called everytime a user connect or disconnect to the hub 
    */ 
    } 
    $.connection.hub.start(); 
    

现在有了这个,我在实时获取所有在线用户。
说明:这是一个InMemory解决方案。其他的解决方案here

希望这有助于...

+0

感谢您的建议,以及@DrewKennedy,我会期待它! – RoyalSwish

+1

好的,现在我将在这里添加一个简单的解决方案,以便您知道从哪里开始。 –

+0

非常感谢,非常感谢! – RoyalSwish

0

我会创造我自己的系统定义什么是你的“活跃”用户:

  • 你可以把你的用户的轨道与字典存储在System.Web.Caching.Cache类中。
  • 在您的基础控制器中(因为它将实例化任何 客户端请求)通过调用KeepTrackActiveUsers方法将当前用户插入缓存字典 。
  • 将SetInactiveUser方法添加到您的注销方法。

{

private Dictionary<int,DateTime> ActiveUsers 
{ 
    get 
    { 
     if(Cache["ActiveUsers"] == null) 
     Cache["ActiveUsers"] = new Dictionary<int,DateTime>(); 
     return Cache["ActiveUsers"]; 
    } 
    set { Cache["ActiveUsers"] = value; } 
} 

private void KeepTrackActiveUsers() 
{ 
    ActiveUsers[CurrentUserId] = DateTime.Now; 
} 

private const int expirationTime = 600; 
private IEnumerable<int> GetActiveUsers() 
{  
    DateTime now = DateTime.Now; 
    ActiveUsers = ActiveUsers 
     .Where(x => now.Subtract(x.Value).TotalSeconds < expirationTime) 
     .ToDictionary(x => x.Key, x => x.Value); 
    return ActiveUsers.Keys; 
} 

private void SetInactiveUser() 
{ 
    ActiveUsers.Remove(CurrentUserId); 
} 

//to be defined 
private int CurrentUserId 
{ 
    get { return default(int); } 
}