在我的应用程序中,我想检查某个特定用户是否已登录,因此我可以显示一个状态,指出该用户是“在线”或“离线”给另一个用户。这个问题是而不是关于验证用户,只关于获取用户的验证状态。ASP.NET MVC - 获取用户的登录状态
我该如何去实现这一目标?
在我的应用程序中,我想检查某个特定用户是否已登录,因此我可以显示一个状态,指出该用户是“在线”或“离线”给另一个用户。这个问题是而不是关于验证用户,只关于获取用户的验证状态。ASP.NET MVC - 获取用户的登录状态
我该如何去实现这一目标?
我认为一个选择是使用一些实时解决方案。例如,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
希望这有助于...
感谢您的建议,以及@DrewKennedy,我会期待它! – RoyalSwish
好的,现在我将在这里添加一个简单的解决方案,以便您知道从哪里开始。 –
非常感谢,非常感谢! – RoyalSwish
我会创造我自己的系统定义什么是你的“活跃”用户:
{
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); }
}
我不认为有一个内置的可用于这一领域。我建议在'AspNetUsers'表的数据库中创建一个自定义布尔字段。在登录时将其设置为true,并在登出时将其设置为false。 –
@DrewKennedy如果有人没有实际登出,而是关闭了标签页或浏览器,或导航到另一个网站,那么这样做会有用吗? – RoyalSwish
当我提出这个问题时,这是我心中的一个限制。答案是我非常怀疑它。这可能必须由JavaScript来完成,但我无法提供确切的答案。 –