0

我之前在网上看到过很多关于这个的问题,但是,在大约 30 个论坛等等中,没有一个有我需要的解决方案,其中包括 stackoverflow。如果有人可以帮助我找到可靠的解决方案,将不胜感激,因此在此先感谢!

我将尽可能详细地解释我的网站和情况,以帮助任何想帮助回答我的问题的人。这是我的情况:

我有一个网站,我使用 PHP 和 MySQL。我的网站是一个“私人”组织网站。为了允许人们访问该站点,我发送了我们组织的新成员并邀请代码。然后用户访问该网站,index.php 文件只包含一个用于登录的表单以及一个指向注册页面的链接。新会员点击“在此注册”链接开始注册。第一个注册页面询问用户的姓氏和邀请代码,这些信息会根据数据库进行检查,以确保该人在列表中并且尚未注册。如果他们通过检查,他们将被带到下一页,在其中输入所需信息(用户名和密码、电子邮件地址等)以及一些可选信息(电话、个人简历等)。如果用户创建了有效的用户名和密码并填写了所有必填字段,则他们的信息将存储在数据库中。密码都经过适当且安全的加盐和散列处理,因此没有问题,整个注册过程都可以正常进行。注册后,用户将返回 index.php,他们现在可以使用刚刚创建的用户名和密码登录。这也有效;当用户登录时,将根据数据库检查他们的用户名和密码,如果成功,则用户已登录。当用户登录时,数据库中的 ONLINE 值从 False 设置为 True。用户现在已登录并可以按预期使用该站点。在我的网站上,有一列列出了当前在线的用户(基于数据库中的 ONLINE 值)。当用户单击站点每个页面上的“注销”按钮时,logout.php 脚本将运行,结束会话并将 ONLINE 值设置回 False。这一切都很好而且花花公子,但是,当用户没有先注销就关闭浏览器时,问题就来了。这是我在互联网上不同地方看到许多不同“解决方案”的地方。我将解释为什么它们不起作用以及为什么我需要更好的解决方案。

我最常看到的答案涉及某种会话超时或破坏会话,这是无关紧要的,因为会话实际上已经在用户关闭浏览器时结束,但这对告诉其他用户是否该人当前是否在线。会话结束时,数据库不会更新,这会导致问题,因为用户只能从单个实例登录。如果用户在其 ONLINE 值已设置为 TRUE 时尝试登录,则不允许他们登录。

我还看到了使用“上次看到”值而不是在线值的建议,如果用户在过去的 x 分钟内没有任何活动,请注销用户。然而,这行不通,有两个原因。1)该脚本仍然必须在某个地方运行才能使其工作,这意味着必须有另一个用户登录才能使其工作。这基本上意味着,如果使用此方法,如果用户关闭浏览器或断开连接,他们将无法重新登录,直到另一个用户登录。我的组织是一个小型的本地组织,因为它也就是说,可能有很多次没有用户在线。此外,即使其他用户登录,连接丢失的用户仍然无法重新登录,直到经过 x 分钟,

我遇到的一个不太常见的解决方案涉及使用 onBeforeUnload JavaScript 函数,但这些最肯定不会起作用,因为它们会在用户单击链接或“后退”和“前进”按钮时触发。此外,如果用户在他们的浏览器中禁用了 JavaScript,这将根本不起作用。

我看到的最后一件事涉及 while 循环和 connection_aborted 函数,这是唯一一个似乎可以工作的函数,但我还没有看到关于它应该如何工作的非常清晰的描述,并且在花了几个月的时间进行试验之后,我仍然没有想出一个可靠的解决方案。

在许多论坛中,我看到人们说“这是不可能的”,但考虑到有些网站以某种方式做到这一点,情况并非如此。我已经在几个站点上对此进行了测试和试验。在拥有 Facebook 或任何论坛网站等用户的网站上,有一个“在线”用户列表,如果用户关闭浏览器,他们的名字将不再出现在列表中,因此有可能,即使只能通过一些晦涩难懂的方法来实现。因此,如果有人知道解决方案,如果您能分享您在这个主题上的一些智慧,我将不胜感激!

4

2 回答 2

0

尝试在 javascript 中创建心跳机制。此方法将在及时使用时开始向您的 webmethod 发送 ajax 调用。

setInterval(function(){
sendPulse();
},30000);


sendPulse(){

var varUserID = userID;//any unique user identifier that can be found on server side
$.ajax({

    url: "Default.php/updateUserStatus",
    UserID: varUserID,
    type: "POST",
    dataType: "json",
    contentType: "application/json; charset=utf-8",
    success: function (mydata) {

        //alert("pulse sent");
    }
    });
   }

在服务器端,您必须有一个具有相同名称和区分大小写参数的方法。应该是静态的并标记为 webmethod。在此方法中为用户保存当前时间。您应该有一种机制来了解用户的脉搏非常旧,当用户尝试做某事或执行任何操作时执行此检查。我已经实施了这种方法并且效果很好。

于 2013-10-05T19:34:29.513 回答
0

这就是答案:客户端和服务器之间的持久连接。为此,您将需要一个 TCP 连接,例如现在的 websockets,或者一个闪存旧的双工连接。从这里开始,当有人连接或断开连接时,TCP 会注意到您。你要做的是一个 websocket 服务器(例如),它只是 traks 连接(从数组中推送和弹出),也是一种响应“get_users_online”消息的方法。您可以通过websocket服务器访问您用户的会话(只读),然后查看用户是否登录(这样您可以将他的昵称存储在会话中,从websocket服务器进一步访问),看看他是否登录管理员(会话-> is_admin)。

很简单,我会说。

这是我一直在使用的库: http: //socketo.me/。它使用一个库来解码 symfony2 会话,但对于简单的应用程序,您不需要解码(symfony2 应用程序对会话进行编码,因此 websocket 服务器必须对其进行解码)。

重要说明:会话必须像 ORM 或 NoSql 一样存储在外部(而不是文件系统 /tmp 中)。

无论哪种方式,请原谅我,但我不得不说,看到的“最后一次”非常好。大多数网站都依赖于此。你理解错了,你不需要有一个活的服务器来检查“最后一次”,当你请求 /admin.php?users_online=1 时,你会查询“Last seen > NOW() - 5 minutes "(这样写是行不通的),所以你甚至可以去掉 "ONLINE" "OFFLINE" 字段。

我建议使用 websocket 方法,这很有趣。:)

祝你好运!

于 2013-10-06T08:14:49.827 回答