2009-06-06 107 views
6

我已经创建了一个登录系统在PHP登出功能等,但我需要会议在窗口关闭销毁。这需要“即时”或尽可能快地将用户状态更改为离线。我真的不想在会话中设置时间,因为这对于用户必须始终登录而言很烦人。关闭窗口会话?

欢迎任何建议,谢谢。 =)

回答

6

默认情况下,PHP发送的所有会话cookie在浏览器关闭时都会被删除。但据我所知,你想在其他浏览器上显示通知。这有点困难,不太好。你必须使用window.onclose事件处理程序,并向服务器发出一个Ajax请求(我相信它应该是一个同步请求)以发出窗口关闭的信号。同步呼叫不是那么好...

另一方面,其他浏览器将不得不拉动服务器与其他Ajax请求,以查看某个用户何时注销。

所有这些Ajax请求都会产生一个丑陋的解决方案。

更新:

由于Thorarin和乔纳森Fingland说,有可能是问题的多个窗口(不是标签,如在窗户没有标签window.onclose火灾),但我相信有这个问题的解决方案太。如果第一个窗口设置了一个cookie number_of_windows = 1,对于每个打开的窗口,该值都会递增,然后在窗口关闭时,只有当number_of_windows等于1时才触发Ajax请求,否则它只会递减number_of_windows

更新2:

上述解决办法,事实上,有多个打开的选项卡的麻烦。我在想如何缓解这一点。

更新3:

OK,我想通了某种形式的解决方案,但它不是在IE6的工作,不知道其他的IE版本。下面的代码片段记录了打开的窗口和标签的数量(IE之间没有实时更新document.cookie,但我相信它可以通过一些IE专有功能来解决)。然后在每个页面上卸载,这意味着甚至可以在同一网站上从一个页面到另一个页面进行导航,该脚本检查以查看有多少个打开的窗口。如果它是唯一打开的窗口/选项卡,则会发出Ajax请求。这是解决方案的第一部分。现在,第二部分。

在服务器端,Ajax调用请求的脚本应该更新数据库中的某些条目,说用户可能已关闭该页面。你如何判断她是不是只访问你网站上的一个新页面?很简单,在每一页访问中,您检查数据库是否可以注销该会话的值,并且如果您将它们标记为false(用户已登录),则用户会一直注销数据库(true旗)。

这很麻烦,但它是我想到的唯一解决方案,因为我无法确定在JavaScript中重新加载页面或类似内容。另外,我没有做广泛的测试,更多的是一个想法。无论如何,我不会推荐这个解决方案。对每个更改页面的Ajax请求都是过度杀毒,并且在服务器上的命中数字翻倍,而不计算其他浏览器所做的轮询。

以下是摘录。顺便说一句,bakery.js是document.cookie的一个小包装。你可能会发现its source here on github

<!DOCTYPE html> 

<html> 
<head> 
<meta charset="UTF-8"> 
<title></title> 
<script type="text/javascript" src="bakery.js"></script> 
<script type="text/javascript"> 
var logout = function() { 
    var xhr = new XMLHttpRequest; 
    xhr.open("GET", "logout.php", false); 
    xhr.send(null); 
}; 

window.onload = function() { 
    var winNumber = parseInt(IGS.Bakery.getCookie("winNumber"), 10) || 0; 
    IGS.Bakery.setCookie("winNumber", winNumber + 1); 
}; 

window.onunload = function() { 
    var winNumber = parseInt(IGS.Bakery.getCookie("winNumber"), 10) || 0; 
    IGS.Bakery.setCookie("winNumber", winNumber - 1); 

    if (winNumber === 1) { 
     logout(); 
    } 
}; 

var showCookies = function() { 
    alert(IGS.Bakery.getCookie("winNumber")); 
}; 
</script> 
</head> 
<body> 

<a href="#" onclick="showCookies();">show</a> 

</body> 
</html> 

忘了提。 window.onclose不是跨浏览器的。

+1

也不正如在thorarin的例子中指出的那样可靠地工作,因为多个窗口/标签可以在同一个站点上打开。第一个关闭会导致会话被杀 – 2009-06-06 13:34:08

+0

感谢您的建议 – Elliott 2009-06-06 13:44:39

3

您可以使用JavaScript来实现OnUnload事件,并使用AJAX与离开该站点的用户进行通信。但是,当他们导航到另一个页面时也会发生此事件。如果您考虑到多个窗口打开的可能性,您必须实施类似于“如果用户不在x秒内请求新页面”的情况,他已离开我的网站,但它不会可靠地工作。

做到这一点的唯一方法是定期对服务器进行AJAX回发,以确保用户仍在您的页面上。但它仍然不会立即。

您可以尝试尝试使用您要发回的脚本。在响应之前建立一个重要的等待期。当用户离开您的页面时,浏览器将可能中止正在进行的XmlHttpRequest。您的服务器端脚本可能会注册客户端断开连接,并断定用户再次离开...,除非他们继续加载另一个页面。

总之,没有明确的方式做到这一点干净的方式。

1

您可以分隔实际登录的“显示为已登录”的概念。例如,每当用户请求某个页面时,您可以将其标记为“在线”几分钟,但您可以设置其实际登录超时到几个小时。在这种方案中,如果用户离开他们的计算机,该网站会在几分钟后将他们显示为“离线”,但他们仍然可以在一小时左右返回并且不必重新登录。