我需要以这种方式只限制一次登录,这样用户就不能同时使用一个帐户多次登录。此外,用户可以登录到不同的服务器上,所以我不能使用session_delete,我需要"手动"删除会话。
当使用带有文件存储的会话时,它工作得很好,我删除文件,登录新用户都很好。然而,当我将会话与memcache一起使用时,我可以从memcache中删除会话,但在同一请求中的进一步登录将丢失。
我就是这样做的:
session_regenerate_id();
$session_id = session_id();
$m = new Memcache();
$m->connect('XXX.XXX.XXX.XXX', 11211);
$ans = $m->delete(SESSION_ID_OF_ALREADY_LOGGED_USER);
$query = "UPDATE activeLogins SET activeSession = '{$session_id}' WHERE userEmail = $safeEmail LIMIT 1";
$dbh->exec($query);
//Login new user...
知道可能出了什么问题吗?
根据数据库中存储的内容检查会话id
据我所知,您希望将一个用户限制为一台客户端机器。这台机器应该是最后一台登录的机器。我认为您应该能够通过对每个页面加载进行简单的检查来实现这一点。
从您的问题中,我可以看到您的数据库有一个名为activeLogins
的表,其中至少包含以下字段:activeSession
和userEmail
。
由此,我认为这是唯一标识用户的电子邮件地址。因此,在新登录后,您将在activeLogins
表中获得一个$session_id
、$safeEmail
和相应的更新行。
现在假设用户没有从旧机器中注销?在那里加载下一个页面时(在更新activeLogins
表之前)会发生什么?对,activeSession
将与该服务器上的$session_id
不同。请记住,新登录更改了它。
因此,您所需要做的就是检查$session_id
是否与activeLogins
表中的activeSession
匹配。
我还建议只在新登录后更新activeLogins
表,而不是在每次页面加载时更新。尽管从你的问题中还不清楚你是否这样做。
我不确定这是否真的回答了你的问题。这似乎是一个简单的答案。但是你的问题不是很清楚。你真的在每次页面加载时都按照这个顺序使用你向我们展示的代码吗?!
作为对您所有答案的回应,我一直在寻找将通知从服务器推送到客户端机器的最佳方式。您自己提到的一种方法是ajax轮询,但我认为这是一种糟糕的做法,不应该使用。
有棘轮(http://socketo.me)它给你一种持续的联系。当检测到另一个登录时,您可以简单地删除连接,并在旧客户端中对此做出反应。
还有一个更高级别的接口,用于将事件从服务器发送到客户端:
https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events
但IE不支持这一点,因此它通常不可用。
你也可以看看http://pusher.com
所有这些建议的要点是,你可以有效地向客户端发出信号,表明它应该删除对你服务的网站的访问,而不需要不断地轮询。