1

I have a script that uses PHP SESSION. I manage PHP sessions using a class. Within this class I have a method that returns how many seconds remaining before the session expires.

Also, Evey time the user refresh the page or open a new page (new request to the server) the idle time counter starts over $_SESSION['MA_IDLE_TIMEOUT'] = time()+900;

What I am looking to do is display a dialog message 2 minutes before the PHP session expire and check if the user is still on the page or not. If the use clicks "Keep working" then the jQuery script will send PHP AJAX request to renew the session $_SESSION['MA_IDLE_TIMEOUT'] = time()+900;. If the user did not click anything or clicked on "Log out" then the session ends and the user is redirected to the login page.

I did find a nice plugin that will somewhat does the Job jquery-idle-timeout

The issue with this plugin is that it checks if the user is idle using JavaScript (if the keyboard/mouse) are being used. Here is the senario where this script does not help me: lets say my PHP sessions has a limit on 15 minutes/ 900 seconds. A user is reading a super long article on the same page. He/she will be scrolling, they are not really idle "from JavaScript perspective" but from a PHP perspective the use is idle. Then after 20 minutes the user refresh the page, then the user will be logged out since he/she have not sent a new request to the PHP server for over the 900 seconds limit.

How can I solve this problem? is there a better plugin to does the trick? if there something I missed in this plugin that will solve my problem?

Thanks

Jaylen
  • 39,043
  • 40
  • 128
  • 221
  • The server-side cannot be aware of the client side unless you update and check the server-side from the client frequently. Your solution may be rooted in detecting movement and sending an AJAX request to update the timeout each time or in blocks of time that are acceptable - such as every two minutes. Then you could employ the non-movement time to ask the question - which would cause movement and send the AJAX request to extend. – Jay Blanchard Oct 23 '14 at 21:34
  • In a general sense, you could use `setTimeout` to pop up a message and delay it by the amount of seconds remaining before the session expires - 2 minutes. – Matt Oct 23 '14 at 21:36

2 Answers2

2

If the user is not making requests, and is not moving the mouse or keyboard or touching the device, etc., then from the app's point of view the user is "idle" even if their eyeballs are not.

If the user is scrolling you can use javascript to listen for scroll events (via onscroll, for example), but this will not be 100% reliable because (1) depends on javascript, and (2) doesn't work if you are viewing a short article or using a tall/large format monitor (like the ones you can rotate 90 degrees, for example).

Perhaps you could handle this differently: use cookies, single sign-on or similar techniques to pre-authenticate or automatically authenticate requests so that the user's session can safely die and be restarted without the user having to manually login.

The other way you could handle this is to maintain a "ping" process that routinely pings the server (via setInterval(), for example) to keep the session alive, and uses a separate timeout (maybe something like the "Authentication timeout" that ASP.NET uses) to keep track of when the "idle" user should be logged out. Then user actions such as scrolling, requesting pages, focusing in fields, moving mouse, etc., can do a "ping reset" that resets the idle counter to 0.

Example / Concept - leaving as exercise for reader to perfect it:

var idleTime = 0; // how long user is idle
var idleTimeout = 1000 * 60 * 20; // logout if user is idle for 20 mins
var pingFrequency = 1000 * 60; // ping every 60 seconds
var warningTime = 1000 * 60 * 2; // warning at 2 mins left
var warningVisible = false; // whether user has been warned
setInterval(SendPing, pingFrequency);
setInterval(IdleCounter, 1000); // fire every second
function IdleCounter() {
    idleTime += 1000; // update idleTime (possible logic flaws here; untested example)
    if (console) console.log("Idle time incremented. Now = " + idleTime.toString());
}

function SendPing() {
    if (idleTime < idleTimeout) {
        // keep pinging
        var pingUrl = "tools/keepSessionAlive.php?idleTime=" + idleTime;
        $.ajax({
            url: pingUrl,
            success: function () {
                if (console) console.log("Ping response received");
            },
            error: function () {
                if (console) console.log("Ping response error");
            }
        });

        // if 2 mins left, could show a warning with "Keep me on" button
        if ((idleTime <= (idleTimeout - (idleTimeout - warningTime))) && !warningVisible) {
            ShowTimeoutWarning();
        }
    } else {
        // user idle too long, kick 'em out!
        if (console) console.log("Idle timeout reached, logging user out..");
        alert("You will be logged off now dude");
        window.location.href = "logoff.aspx"; // redirect to "bye" page that kills session
    }
}

function ShowTimeoutWarning() {
    // use jQuery UI dialog or something fun for the warning
    // when user clicks OK set warningVisible = false, and idleTime = 0
    if (console) console.log("User was warned of impending logoff");
}

function ResetIdleTime() {
    // user did something; reset idle counter
    idleTime = 0;
    if (console) console.log("Idle time reset to 0");
}
$(document) // various events that can reset idle time
.on("mousemove", ResetIdleTime)
    .on("click", ResetIdleTime)
    .on("keydown", ResetIdleTime)
    .children("body")
    .on("scroll", ResetIdleTime);
nothingisnecessary
  • 6,099
  • 36
  • 60
  • If I keep sending pings to the server then I will never become idle. I think what i need to do but not sure how to code it, is every minute or so I should send a AJAX request the server to get the remaining session time and depending on the returned value display dialog or not. – Jaylen Oct 23 '14 at 22:04
  • That is why you use the separate timeout (NOT session timeout) to control the logout. So as long as the web browser is open it will keep the session alive, up until the point where the idleTimeout is reached (the idleTimeout is an arbitrary choice that has nothing to do with session timeout). I have used this technique successfully for years with ASP.NET apps, where the Session timeout is very low (like < 5 mins), and the authentication timeout defines when the "idle" user gets logged out. That way if user closes browser, Session is freed very quickly, releasing resources, etc.. – nothingisnecessary Oct 23 '14 at 22:07
  • Oh, and make sure that when you determine "user idle too long" that you send a request that explicitly kills session. It is not uncommon for web apps to have a "logout" page that does this, and shows a friendly message like, "You have been logged out; please close your browser! See you next Tuesday!" etc – nothingisnecessary Oct 23 '14 at 22:34
1

I use a time cookie to log out an inactive user like this:

`$time = time();
// 5 minutes since last request
if(!empty($_COOKIE['_time'] && $time - $_COOKIE['_time'] >= 300) 
{
    // log user out
}
setcookie('_time', $time, '/');`

Hope this helps.

mocanuga
  • 131
  • 4