【问题标题】:Deleting memcache session from remote server从远程服务器删除 memcache 会话
【发布时间】:2014-10-14 12:04:58
【问题描述】:

我只需要以这种方式限制一次登录,这样用户就不能一次使用一个帐户多次登录。用户也可以登录到不同的服务器,所以我不能使用 session_destroy,我需要“手动”删除会话。

将会话与文件存储一起使用时效果很好,我删除文件,登录新用户都很好。但是,当我将会话与 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...

知道可能出了什么问题吗?

【问题讨论】:

  • 你的登录和会话/内存缓存存储过程有点不清楚atm。还有更多的代码 sn-ps/解释吗?
  • @ToBe Login 是简单地将会话变量存储为 true。 Memcache 会话存储在 php.ini 中通过更改 session.save_handlersession.save_path 进行更改。另外我发现这个 当页面完成时,它会将会话中的数据推送到 memcached。最后一步很关键,因为它控制着 memcached 中数据的过期时间。 发现 here
  • 您是否验证了使用 memcache 的会话确实有效?如果有疑问,请创建一个非常小的 PHP 文件以排除代码中的任何错误,并尝试使用一个会话变量。
  • 会话确实有效,我通过 ssh 连接到 memcache 服务器,查询了特定的会话 ID,我确实看到了结果。正如我所说,即使这个删除部分也有效,但它是在页面末尾执行的,并且在删除语句之后每次写入会话都不会存储在内存缓存中。嗯,实际上现在我想到了,在删除语句之后将某些内容存储到会话中(编码数据,因此无法真正看到),但用户未设置为已登录...我将在外部文件中进行测试。 Tnx。
  • 不,如果你的会话处理程序存储了它的信息并且它也从内存缓存中检索它,那么会话就可以工作。您永远不必自己操作该内存缓存,因为它实际上可能导致会话损坏。尝试通过正常的会话机制删除会话内的变量。不要直接访问 memcache。

标签: php session memcached


【解决方案1】:

根据数据库中存储的内容检查会话 ID

据我了解,您希望将一位用户限制为一台客户端计算机。那台机器应该是最后一台登录的机器。我认为您应该能够通过对每个页面加载进行简单检查来实现这一点。

根据您的问题,我可以看到您的数据库有一个名为 activeLogins 的表,其中至少包含以下字段:activeSessionuserEmail

据此,我假设它是唯一标识用户的电子邮件地址。因此,在新登录后,您将拥有 $session_id$safeEmailactiveLogins 表中相应的更新行。

现在假设用户没有从旧机器上注销?那里的下一页加载会发生什么(在更新activeLogins 表之前)?对,activeSession 将不同于该服务器上的$session_id。请记住,新登录名已更改。

所以您需要做的就是检查$session_id 是否与activeLogins 表中的activeSession 匹配。

我还建议只在新登录后更新activeLogins 表,而不是在每次加载页面时更新。虽然从你的问题中不清楚你是否这样做。

我不确定这是否真的回答了您的问题。这似乎是一个简单的答案。但是你的问题不是很清楚。你真的在使用你在每次页面加载时按顺序显示给我们的代码吗?!

为了响应您的所有回答,我寻找了将通知从服务器推送到客户端计算机的最佳方式。您自己提到的一种方法是 ajax 轮询,但我认为这是一种不好的做法,不应该使用。

Ratchet (http://socketo.me) 可以为您提供持续的连接。当检测到另一个登录时,您可以简单地删除连接并在旧客户端中对此做出反应。

还有一个更高级别的接口用于从服务器向客户端发送事件:

https://developer.mozilla.org/en-US/docs/Server-sent_events/Using_server-sent_events

但 IE 不支持,所以一般不可用。

你也可以看看http://pusher.com

所有这些建议的重点是,您可以有效地向客户端发出信号,指示它应该删除对您正在服务的站点的访问,而无需不断轮询。

【讨论】:

  • 感谢您的回答,我实际上需要立即注销用户(+/- 几秒),不仅在页面加载时,而且我想我也可以使用您在 ajax 请求中所说的内容.. . 代码库比我提供的示例更大更复杂,但我想缩小范围。我没有在每个页面加载时使用确切的代码,它仅在登录时使用。简单的答案,但我没有朝那个方向思考,我会考虑它,谢谢。
  • 啊,我明白了。好吧,没有确定的方法可以控制客户端计算机上的浏览器。但是假设用户已经打开并离开了 Javascript,您可以使用常规的 ajax 调用(每分钟一次?)来检查 session_id 是否没有改变。如果有,您可以删除最后加载的页面并显示“登录到另一个客户端”消息。还要确保它已从浏览器的历史记录/缓存中删除。当然,互联网连接应该是活跃的,这样才能正常工作。
  • 另一种方法是使用 Javascript 来检查用户是否做了任何事情。如果他们有一段时间没有做任何事情,您可以删除加载的页面。这样你只依赖于 Javascript 而不是互联网连接。这对用户来说并不好。您可以仅将其限制为关键页面内容。
猜你喜欢
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
  • 2011-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
相关资源
最近更新 更多