我想让我的网站设置在线用户'当状态为非活动状态或关闭浏览器时状态为0。 如果他们重新打开网站或从空闲状态恢复(超时后),我希望状态恢复为1(除非他们因网站长期缺席而完全注销)
这是我到目前为止所尝试的内容:
Inactive.php
include 'db.php';
mysql_query("UPDATE users SET status = 0 WHERE user_id = ".$_SESSION['user_id']."");
检查浏览器是否已关闭
window.onbeforeunload = function() {
$.ajax({
url: 'inactive.php',
type: 'GET',
async: false,
timeout: 4000
});
};
检查空闲超时
var IDLE_TIMEOUT = 60; //seconds
var _idleSecondsCounter = 0;
document.onclick = function() {
_idleSecondsCounter = 0;
};
document.onmousemove = function() {
_idleSecondsCounter = 0;
};
document.onkeypress = function() {
_idleSecondsCounter = 0;
};
window.setInterval(CheckIdleTime, 1000);
function CheckIdleTime() {
_idleSecondsCounter++;
var oPanel = document.getElementById("SecondsUntilExpire");
if (oPanel)
oPanel.innerHTML = (IDLE_TIMEOUT - _idleSecondsCounter) + "";
if (_idleSecondsCounter >= IDLE_TIMEOUT) {
alert("Time expired!");
document.location.href = "inactive.php";
}
}
我的查询似乎无效。如何判断每隔x秒检查一个用户?
答案 0 :(得分:3)
window.onbeforeunload
会产生竞争条件并且不会非常可靠。您还希望使用window.addEventListener('beforeunload', function () {...});
代替
alert
中的CheckIdleTime
将停止执行javascript
,因此用户必须进行互动(点击OK
)才能退出。否则这种方法似乎很好。
现在,当用户离开网页时,通常您会将Cookie设置为在离开网站时过期,但似乎您希望在您的网站中为活跃用户设置运行记录。
为此你可能需要一个两步的方法,主动设置“最后活动”的标志和时间戳。并且还运行垃圾收集脚本,如果您没有看到它们中的任何活动,则将用户设置为“非活动”。
如果您需要活跃用户的真实实时日志,您可能希望查看Node.js
特别是Socket.IO
,它可以更好地处理实时客户端 - 服务器IO。
运行一个更新用户的查询可能要容易得多,说它们实际上是活动的
<script>
setInterval(function () {
$.post('active.php');
},
15000 // every 15 seconds
);
</script>
在active.php中(假设您添加了新的last_active
DATETIME
,而user_id
是一个int:
mysql_query("UPDATE users SET status = 1, `last_active` = NOW() WHERE user_id = ". (int)$_SESSION['user_id']."");
mysql_query("UPDATE users SET status = 0 WHERE `status` = 1 AND `last_active` < DATE_SUB(NOW(), INTERVAL 15 SECOND)"); // set all in active who have not pinged in the last 15 seconds
以下可能是架构的外观
CREATE TABLE `users`
`id` IN NOT NULL,
`status` INT(1) DEFAULT 0,
`last_active` DATETIME
);
您可能希望在“非活动”时间间隔内玩一下,并考虑创建索引。
答案 1 :(得分:2)
此代码将参考我在此处提供的示例&gt;&gt; jquery-idle with jquery-ui Dialog
使用的图书馆:
嵌入式库示例:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://thorst.github.io/jquery-idletimer/prod//src/idle-timer.js"></script>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/themes/smoothness/jquery-ui.css" />
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js"></script>
没有jQuery对话框:
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script src="http://thorst.github.io/jquery-idletimer/prod//src/idle-timer.js"></script>
请记住,您可以使用您喜欢的对话框方法切换对话框代码。我将jquery-ui包含在对话框中,以使事情尽可能简单。这也无法处理beforeunload
事件,因为您的代码中已包含该事件,但我建议您在此处进一步阅读&gt;&gt; beforeunload stackoverflow article&lt;&lt;
HTML
这行代码用于存放倒数计时器的占位符。为简化起见,我也在计时器到期时使用它来显示&#34; Session Expired&#34;
<div id="sessionSecondsRemaining" style="font-size: 22px; font-weight: bolder;"></div>
这是一个使用jQuery UI的非常简单的Modal对话框。您可以随意扩展或替换它。
<div id="dialog-confirm" title="Logout" style="display: none;">
<p><span class="ui-icon ui-icon-alert" style="float:left; margin:0 7px 20px 0;">Your session has expired.</span></p>
</div>
没有jQuery对话
<div id="sessionSecondsRemaining" style="display:none;"></div>
CSS
由于灰色背景中的错误无法正确显示jQuery UI模式对话框(为什么还没有修复 - facepalm ),这只是一个小小的黑客攻击。
/* override jquery ui overlay style */
.ui-widget-overlay {
background-image: none !important; /* FF fix */
background: #000 url(images/new-ui-overlay.png) 50% 50% repeat-x;
}
没有jQuery对话
的Javascript
您可以在此部分配置jquery-idletimer的参数。
var
session = {
//Logout Settings
inactiveTimeout: 10000, //(ms) The time until we display a warning message
warningTimeout: 10000, //(ms) The time until we log them out
minWarning: 5000, //(ms) If they come back to page (on mobile), The minumum amount, before we just log them out
warningStart: null, //Date time the warning was started
warningTimer: null, //Timer running every second to countdown to logout
logout: function () { //Logout function once warningTimeout has expired
//window.location = settings.autologout.logouturl;
},
//Keepalive Settings
keepaliveTimer: null,
keepaliveUrl: "", // set the Keep Alive URL here (aka keepalive.php)
keepaliveInterval: 5000, //(ms) the interval to call said url
keepAlive: function () {
$.ajax({ url: session.keepaliveUrl });
}
}
;
添加&#39; keepalive.php&#39;支持,只需设置keepalive.php所在位置的完整URL(以及您希望传递的任何参数,因为您正在使用会话,您不需要任何参数)。
keepaliveUrl: "http://example.com/keepalive.php", // set the Keep Alive URL here (aka keepalive.php)
此行初始化并设置#sessionSecondsRemaining
div中的值。
$('#sessionSecondsRemaining').html(Math.round((session.warningTimeout - diff) / 1000));
此部分是您将控制对话框的代码警告会话到期倒计时的用户的位置(通常#sessionSecondsRemaining将在此对话框中)
$( "#dialog-confirm" ).dialog({
resizable: false,
height:140,
modal: true,
buttons: {
"Extend": function() {
clearTimeout(session.warningTimer);
$( this ).dialog( "close" );
},
Cancel: function() {
session.logout();
$( this ).dialog( "close" );
}
}
});
没有jQuery对话
如果您注意到,&#39; Extend&#39;,则终止警告计时器,取消调用注销功能(也可在上面配置)
最后,这个块对于计时器倒计时到零的情况以及控制#sessionSecondsRemaining
内的倒计时显示非常重要
if (remaining >= 0) {
$('#sessionSecondsRemaining').html(remaining);
} else {
$( '#dialog-confirm' ).dialog( "close" );
clearInterval(session.warningTimer);
$( '#sessionSecondsRemaining' ).html('Session Expired');
session.logout();
}
在else
下,可能是您在上面的块中真正需要修改的唯一位置。在那里,我调用session.logout()
函数(应该是清理对话框后的最后一行,但这只是一个演示)。您可以在此处关闭对话框,和/或将用户重定向到会话过期页面,或显示消息。如果停留在同一页面上,请务必clearInterval(session.warningTimer);
。如果没有,那么那条线并不重要。
没有jQuery对话
if (remaining >= 0) {
$('#sessionSecondsRemaining').html(remaining);
} else {
clearInterval(session.warningTimer);
session.logout();
}
if (session_status() !== PHP_SESSION_ACTIVE) { session_start(); }
include 'db.php';
$maxtimeout = 15; // Seconds for max timeout before forcing session reset on other users.
mysql_query("UPDATE users SET status = 1 WHERE user_id = ".$_SESSION['user_id']."");
mysql_query("UPDATE users SET status = 0 WHERE user_id <> ".$_SESSION['user_id']." AND (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(`timestamp_field`)) > " . $maxtimeout . "";
此任务应设置为运行服务器端以从任何流量清理数据库(如果您有大量活动,那么您不会需要此脚本)
include 'db.php';
// Set this for a longer timeout than in keepalive.php
$maxtimeout = 90; // Seconds for max timeout before forcing session reset on other users.
mysql_query("UPDATE users SET status = 0 WHERE (UNIX_TIMESTAMP() - UNIX_TIMESTAMP(`timestamp_field`)) > " . $maxtimeout . "";
答案 2 :(得分:1)
这就是我在我的系统中应用以跟踪用户仍在线的情况。我让客户端站点每分钟都ping回来告诉DB他还在线。
关于检测浏览器关闭,您可以Close/kill the session when the browser or tab is closed
查看此Daniel Melo<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
</head>
<body>
<script type="text/javascript">
var timeLeft = Number(60);
setInterval(function(){
timeLeft--;
if(timeLeft<0){
expiredLogout();
}
$("#timer").html(timeLeft);
//If timer less than 30, show message to user will logout soon
if(timeLeft<30){
$("#logoutMsg").show( "slow" );
}else{
$("#logoutMsg").hide( "slow" );
}
$("#logoutMsg").html('You will logout soon, in '+timeLeft+' sec.');
},1000);
//Initial Function
$(function() {
//Mouse move top up the time left value;
$(document).mousemove(function(event) {
timeLeft = Number(60);
});
stillAlive();
//Every 1 minute ping the active.php
setInterval(function(){ stillAlive();},60000);
});
//Redirect to other page if time out
function expiredLogout(){
window.location = "inactive.php";
};
function stillAlive(){
//Update userID 1 still active
var postVal = {userID:1};
$.post("active.php", postVal, null, "json")
.success(function(data) {})
.error(function() {})
.complete(function() {});
};
</script>
<label id="timer"></label>
<div id="logoutMsg"></div>
</body>
</html>
答案 3 :(得分:1)
有一个javascript库可能会有所帮助 这是Ifvisible.js。
它将允许您检测用户何时不再处于活动状态。
例如,你可以这样做:
//Handle tab switch or browser minimize states
ifvisible.on("blur", function(){
//ajax call for inactive.php -> SET status = 0
});
ifvisible.on("focus", function(){
//ajax call for active.php -> SET status = 1
});
//Detection of inactivity for xx seconds
ifvisible.setIdleDuration(120); // Page will become idle after 120 seconds
ifvisible.on("idle", function(){
//ajax call for inactive.php -> SET status = 0
});
ifvisible.on("wakeup", function(){
//ajax call for active.php -> SET status = 1
});
当然,您可以使用不同的参数调用相同的inactive.php程序,以了解是否要将状态设置为1或0。 例如,使用您的ajax调用:
// if inactive : SET status = 0
$.ajax({
url: 'inactive.php?status=0',
type: 'GET',
async: false,
timeout: 4000
});
// if active : SET status = 1
$.ajax({
url: 'inactive.php?status=1',
type: 'GET',
async: false,
timeout: 4000
});
在你的Inactive.php中:
if ($_GET["status"] == "1") // status = 1 -> active
$tatus = "1";
else // status = 0 -> inactive
$tatus = "0";
mysql_query("UPDATE users SET status = " . $tatus . " WHERE user_id = ".$_SESSION['user_id']."");
访问网站,获取有关Ifvisible.js的更多信息。
我希望它会对你有所帮助。 :)
答案 4 :(得分:0)
第一个问题是你定义“空闲”的方式。什么终止了“闲置”时期?将焦点转移到浏览器窗口?滚动页面?点击页面?单击按钮?点击链接? - 后者似乎是大多数网站使用的方法,这可以单独在服务器端完成:如果用户没有在您的网站上打开另一个页面,比如5分钟,那么他被认为是空闲的。 15分钟后,他被系统注销。