This question already has answers here:
How to know browser idle time?
(5 answers)
Closed 7 years ago.
In building a monitor, which would monitor any activity on the browser by the user, like click of a button or typing on a textbox (not mouse hovering on document). So if there is no activity from the user for a long time, the session will time out.
We need to do it without jQuery or anything such. I may use ajax. Java servlet in other end is preferable.
The problem with the approach you suggest is that the session will time out, even if the user is moving the mouse or typing in an input. So if you have a session timeout set to 20 minutes, and the user keeps typing for 21 minutes, the session will still time out, even though they have been "active". The only thing that will keep the session from timing out is a new request to the server.
Solution 1: Let the server be in control of the session timeout
Unless you are making Ajax-requests in the background, that will keep renewing the session, you could just set a JavaScript-timeout when the page loads, and alert the user that way. Unless you make other requests to the server, while the user is on your page, there is no need to make it difficult:
setTimeout(function () {
alert("You've timed out baby!");
}, 1200000); // 20 minutes in millisec (modify to your session timeout)
If the user visits another page or reloads the page, the session is renewed and the JavaScript timer is reset. If the user does no such thing, the session will time out at the same time the user gets her alert.
Solution 2: Let the client be in control of the session timeout
If you want the JavaScript to be fully in controll of how long the session lasts, so that it is renewed whenever the user types, moves the mouse or whatever, you will have too keep making Ajax-requests in the background to your server, so the session is renewed. (That could be an empty dummy request, just something that hits the server)
You would then have to track all actions you consider "user activity" (AnhSirk suggest one way in his answer) and reset the timeout timer whenever such an event occur. If the user is inactive for too long, you would then have to make an Ajax-request to a page on the server, that invalidates the session, and then you can alert the user that the session has timed out.
Related
I am working on implementing a "presence" feature on a website built on a classic asp (vbscript), SQL Server, javascript, IIS7 stack.
The existing authentication/log in system uses sessions, with a default 20 minute session timeout. The user data is stored in a SQL Server table. A cookie is also set when a user logs in, which enables tracking of registered users even when not logged in.
There is a column in the USERS table which holds the state e.g. "online" or "offline". The following is the logic I've come up with thus far:
Status is set to "online" when:
user logs in
a cookie is detected e.g. user returns but doesn't yet log in
Status set to "offline" when:
user logs out
user closes browser (use a javascript event to detect)
user navigates away from the site (not sure yet how best to detect this)
users session expires (handled in global.asa's Session_OnEnd subroutine)
Questions:
Am I overlooking anything in the logic presented above?
What is the best way (within js / classic asp) to detect items 2 and 3 above in the "when to set status to 'offline'" list
Thanks
With 2 and 3 there are js restrictions as to what you can do when js detects a potential leaving of the page. I think all you can do is to show a message before they leave. This means you wont be able to run any js as they are leaving.
Best way to detect when a user leaves a web page?
As Gary said probably the most effective way is to use some ajax to ping a script on the server to update a LastTimeOnline field in your db.
Another way is to use the Session_OnEnd but this may give a false figure as a user could be online for 5 secs which would trigger a 20 minute session.
Best to do the ping really.
All the other logic you have there seems fine.
Just spotted your other comment. Yes if someone leaves their browser open at the page then potentially this could be pinging all day. But then they maybe online so you'd have no choice but to presume that a session is active really. You could always add a bit of js that detects clicks and scrolling to determine activity.
IMHO, the best way to handle 2 and 3 is to have the client send a ping every x seconds, update last access time in DB, then have a logout function on the server side that looks for non-access within x amount of time, and update flag.
These automatic pings will make it seem like there is activity from the client when there may not be, and in this case add some events that capture mouse and keyboard activity. If they stop for some period of time, stop sending pings. Restart pings when activity resumes.
A ping is the only way that you will be 100% sure that the user is still there. Think of example where a user just shuts off the machine. You will not know that they are gone until 20 minute timeout expires. If you set your ping for 60 seconds, you will know very quickly is a user disappears.
I have an alert that pops up when the users session is about to expire and when it does expire. The issue is that if multiple tabs are open for the app, multiple alerts will get fired in succession which is very annoying.
I'd like to make a check on the backend for session information before showing an alert. That way if in one tab the session is about to expire (according to the front end), but it's not actually about to expire because you've been operating in another tab, the alert won't display and steal browser focus. Ideally I'd like this to remain as an alert so the first and proper display of the warning does take browser focus.
So is it possible to make a request like this without refreshing the session?
Trying to do this in JavaScript is silly - it will be really hard to keep the countdown timer in sync with the PHP session.
If you are implementing a hard timeout on the session then you must already be using a custom session handler - so simply implement a variant of that in your Ajax responder which does not lock or write back the session.
OTOH if you're not really implementing a hard session timeout, and you are not already using a custom session handler (which I suspect really is the case). Then just check the timestamp on the session file.
I am building a WebApp (ERP) and I need to display the people currently logged in and active on the page. I managed to get something pretty accurate by listening on the mouse/keyboard events and periodically reporting to the DB.
I don't know how to mark people offline when they close the page. I tried using onbeforeunload, but it obviously fires when the user simply changes pages (click a link inside the ERP, that point to another page in the ERP).
I then tried to use WebSockets, but the problem is the same : everytime the page is realoded, the WebSockets connection is closed.
So I can think of two ways:
Use WebSockets indeed, and replace all links by a call to a javascript function that would somehow tell the server that the user is going to change page (so that the server doesn't mark it as offline). But that doesn't feel right, semantically speaking, links should be links, it simply points to another location.
Use either WebSockets or AJAX and never actually change page: links are replaces by a function that will call for the content, and display it on screen (updating the DOM with Javascript). But again, it doesn't feel right either, because semantically speaking the page would have no meaning and the URL would never change, so the user can't "copy paste" the link of the page to refer to it, right ?
So, is there a proper, clean way of doing this? Thanks for your help.
If each of your pages has a webSocket connection to your server, then on the server you can see when any given page is closed by seeing that the webSocket gets closed.
To avoid thinking that a user has left the site when they are just navigating from one page in your site to another, you simply need to add a delay server-side so that you only report that the user has left your site if there has been no webSocket connection from this user for some time period (probably at least a few seconds).
So, on your server when you detect that the last webSocket connection for this user has been closed, you set a timer for some number of seconds. If the user opens up another page on your site (either via navigation or just opens another page) before the timer goes off, you cancel the timer and count the user as still connected. If the timer goes off, then you now know that the user has been away from your site for whatever time period you picked (say 10 seconds) and to you, this will signify that they have left the site. You can control how long you want that time period to be before you decide that, yes they are gone.
All attempts at trying to "see" the user leaving your page IN the browser with Javascript are going to have holes in them because there are always ways for a web page to get closed without your client-side javascript having a chance to tell your server. The beauty of the webSocket solution is that the browser automatically and reliably tells your server when the page is now gone because it closes the webSocket and your server receives the notification that the socket has been closed.
As I understand you want to compute users active on website/pages.
Identify the user (99% unique id computed):
http://valve.github.io/blog/2013/07/14/anonymous-browser-fingerprinting/ you can use another library, there are few.
On each page send from time to time at page load meaning user is navigating or (60sec you can chose lower time frame meaning user is staing on the page) computed id (fingerprint js) to server (web-socket/ajax)
On server you need to have list of id's with expiration date (60s) increment when new user log's in (stored in database or session).
Retrieve on your website the count (60sec ajax/websocket) of id's having timestamp <= server time - let say 120sec.
Knowing if user is logged, and specify the page:
use an object to be sent at server {fingerprint: 123123124234, logged : true, page: home}
Clear your list if you are not storing in Database the users:
Separate thread (server only) access the object and destroy all nodes older then 10 min or whatever your page session is set.
js timer: http://www.w3schools.com/jsref/met_win_setinterval.asp
Let hope it's helpful, id did something similar using the timer at 5 min to sent to server if user is still on the page, or signal at page load.
Getting the cont of users in frame of 60 sec. And even the users with names present on page :)
Somebody already post this kind of question.
Hope this could help you .
Detect if user has closed ALL windows for a website?
I am working on an app that must use session timeouts.
The problem is that users regularly miss the session timeout and lose data. I already implemented a small session keeper in javascript that will renew the session every one minute if there has been some activity in the browser, but users are still somehow losing data (assumably they are half filling out a form, walking away from their machines and coming back after the session has expired and submitting the form.)
I would like to find some way to warn them that their session has expired. The problem is that I can't figure out exactly how to do it. I can't check the expiration of the session cookie in javascript, because it's an HttpOnly cookie, and if I do some kind of AJAX request to check the status of the session, it will automatically set a new expiration for the session.
Can anyone see a way around these obstacles?
This isn't a direct answer about checking session time-outs... but I've found garlic.js to help when I'm worried about users losing their work in forms. Basically, it's a JS library that takes care of saving form data in the user's browser's local storage until the form is submitted. So that, in case the browser closes or the session expires, the data is not lost. So this may be a good backup solution for the from data getting lost part.
UPDATE:
What I typically do to avoid form submission after session timeout is to set a javascript timer that will auto redirect the user to a session expired page (with an easy log in again button) a few seconds after the typical session timeout length. (You could reset this timer with your AJAX polling when there is activity within the page.) This combined with garlic.js, combined with "deep dive" functionality (whereby you store authenticated URLs in the session when they're accessed so that after a timeout and log back in you return the user to the last page they were on) creates a pretty seamless timeout, log-in, resume where you left off scenario.
I want to logout user if browser is closed and force it to login again on turning the browser on.
if (!(isset($_SESSION['admin']))) {
header ('Location: login.php');
}
This doesn't work - because turning off the browser does not mean drop the sessions on server - if I understand well a lot of posts on SO and outside.
Using javascript to delete sessions just before closing the browser often doesn't work because browser will not wait to execute any code if user clicks to close the browser.
Second option is keeping server session alive by sending a js code from client (setInterval - ajax).
Problem here is scenario with multiple pages open on different tabs/windows, i.e. interference between multiple setInterval functions.
I also tried this:
session_set_cookie_params(0);
session_start();
This also doesn't work - after turning off/on the browser index.php is open without redirecting to login.php.
The reason is maybe browser option to automatically restore previously loaded pages.
So, what to do ?
#Axalix wrote:
If session relies on cookies, you just need to keep expiry date empty, then when browser / tab is closed this cookie will be removed from a browser automatically. That's a standard browsers behavior. Yes, the server will still keep it, but since browser doesn't have it, user will need to relogin
You responded:
could that be a possible security issue because cookies are javascript stuff - chengable by client?
Yes cookies can be changed by the client but Axalix' answer from the comments is still the best if you intend to use $_SESSION. If you want to end session on browser exit so that a 2nd user doesn't come later and take over the old session, then you must trust the owner of the session with the session cookie.
If you really want to break access as soon as the client leaves, then $_SESSION is not the best tool to track login state. Instead you could use WebSockets. The socket remains open as long as the webpage is open. Once the socket closes, you can invalidate any login state.
This may be more trouble than it's worth though, so think hard about whether it is really that important. As an alternative, you could use SessionStorage, which is destroyed when the browser closes but it's also available to the user (so a user could just copy and save what's in SessionStorage, then recreate it later).
Basically you need to trust the user who provided you the username and password.
There are couple options but all end up same way. you can either store something in sessionStorage to check session. when browser is closed session storage will be wiped out. or you can add a hidden input field and assign a value per session. if page is newly loaded and value exists that means session is still active, so you can redirect to logout and show login page in either way. but second option may not be usefull if your app has page reloads. I think sessionStorage would be your answer. set session on sessionStorage on login, if it is empty. then check session storage on page load. if it is empty that means user first time on there, since page reload will keep the value.
When Google Chrome is configured to re-open all previous tabs, it won't delete your session cookie. See for example this question asked 5 years ago, but stil an issue (just verified, Google didn't change that behaviour). Unfortunately you can't do much about this behaviour (as far as I know). Without deleting that cookie your session still remains open (unless it is deleted server-side during clean-up).
Best solution to handle an automatic logout is to store a 'last activity time' in your session, update it in every request and in your 'is logged in check' verify that the last activity was not more than, say, 15 minutes ago. If it is more than 15 minutes ago, you could send him to the login.php.
To improve this furthermore (and if this is really an issue for you), you can use a setInterval in javascript to send keep-alive AJAX-calls to the server every 30 seconds or so. In that way you can lower the 'last activity time' (either real activity or automated) limit from 15 minutes to 2 or 1 (leave some room for network hickups).