Number of users logged in/out with session expire? - php

I'm running a php login script on my server. Whenever a user logs in the username is stored in $_SESSION['username'] and there exists a field in one of my DB tables called nonline used to store the number of users logged in.
When a user logs in, the value of nonline increases by one. And whenever a user logs out it decreases by one. Pretty neat so far. :P
The problem starts when, most of the users, like me, do not click logout, or visit the logout page as such. They log in, and just close their browser/tab when done. Doing so doesn't decrease the nonline value. So the value remains as such, even when the user is no more browsing my website.
Is there any way I can determine the number of users actually looking at my website at any given time so that its value changes even when a user closes his browser instead of clicking logout? I'm not using cookies for login.

Normally this will be done with a table which tracks last action, or last page load. The number n_online (you may want to add the _, noline starts with no, which is a little odd at first glance) will be the number who have made some form of action in the last n seconds - the number of people who actively logged out.

Unfortunately, there is not. Any solution that does what you want would involve the browser firing an HTTP request of some kind when the tab/window is closed, and this isn't going to happen.
The best you can do is have the users' sessions time out after a relatively short time (e.g. 15 minutes) and perform aggressive cleanup of expired sessions on every script that wants to know the actual number of active users. Be aware that this will be bad for performance.
If 15 minutes is still too long for you and you cannot decrease the session lifetime (because it would annoy your users if they were logged out after 10 seconds of inactivity), you can have your pages "ping" the server using AJAX to keep the session alive. This will allow you to have almost real-time results, but it will probably kill your performance, it will not work for users with JavaScript disabled, and is prone to malfunction if a user experiences transient connectivity problems.

Related

How to get notified about a closed session in PHP

I am keeping a list of active users of my web site.
When user logs in I add them to the list.
Then I periodically (on timer) call a PHP script which delays PHP session expiration time on the server each time by 10 mins.
When users logs out I remove them from the active users list.
As timer is stopped and an expiration is not delayed anymore, a PHP session expires after 10 mins.
So far so good.
When user closes a browser without logging out, their session still expires after 10 mins as a time stamp is not updated anymore.
But this user still remains in my active users list !!
How can I remove this user?
I am keeping this list in order to prevent users from entering from 2 computers simultaneously, that is a client requirement.
EDIT:
I am sure that this can be done as bank sites, ticket sites etc. somehow cope with this problem.
The simple answer is you can't. Not with PHP alone anyway. If you are happy to force javascript usage, you could write a script which would 'poll' the server from the user's browser on very regular intervals to let it know the user was still active.. you would then also reduce the interval set for your PHP script to keep things updated with more accuracy.
You could try updating the "active users" list on a more frequent basis, but it would generally make more sense to clear a user's session data upon each login. Therefore, if a second login occurs from another computer, the first one is terminated upon the next page load.

How to handle browser close logouts in PHP?

I have a problem with logged in users closing their browsers.
My code can't run due to the browser closing and so their logonstatus cant update to 'N' in the database. Also due to the session being destroyed they cant go back to the main pages as I have this code if (!isset($_SESSION['logged in'])) { etc to prevent people from viewing any pages without logging in.
When a user logs on their logonstatus changes to 'Y' and I record the time they logged in.
I record their lastactivity time on each page load.
I redirect users to the login page and change their logonstatus if they have been idle for 20 min on a page.
I also have a cron job due to the browser close issue which runs every 5 minutes and checks if the users last activity has been longer than 20 min and if so their logonstatus becomes 'N'
I think users having to wait 20+ min to re-login due to browser close is too long and so I would like to make it possible to login in again straight away.
I have read about the unload functions of javascript but apparently it is unreliable.
Is there any other way I could go about this?
Closing the browser is always a client side action. So you will need javascript to send the action to the server for PHP to do something.
You can use onbeforeunload to send something to the server, but it is indeed unreliable. A more reliable method is to make the session time a lot shorter (eg: 2min) and then have an ajax call every 30seconds to the server to keep the session alive (make sure its a page with a very small impact on server/connection). If the request fails 4 times, the session is destroyed. Now your cronjob can run every 2mins and a user only has to wait that long.
Another approach is to store a cookie on the users computer with a GUID and save it in the database with the "Logged ='Y'". Now when somebody tries to log in to an account which is already logged in, check if its the same user (cookie) and if so, allow it.
This still makes it possible for one user to log in twice, just harder and not by mistake.
You need to change the duration of your session cookies so that they last as long as the browser window remains open; do this with session_set_cookie_params, setting the lifetime to 0. Don't forget to make sure that your cron script and PHP's session gc max lifetime don't delete sessions before 20 minutes have passed.
Since you keep a record of their last access time and check it on each request, you can continue to log out people after 20 minutes of inactivity (just destroy their session and redirect to the login page).

Logout issues in a single-user system

I've been asked to build a project management application that could only host one user at a time. I managed to do that by simply creating a status row in my user table which is set to 1 when somebody is logged in.
Now, status = 1, nobody else can log in, they get an error message instead saying that another user is already using the application. When the online user logs out, I update the status row in the database and set it to 0 in order to allow other users to log in freely.
Everything is working just fine except, as you can see, it relies on the logout button and many users forget to logout that way, they just close the tab or the browser leaving status as 1 and then blocking the whole system.
I tried a few methods to update the database on page close with session timeout or via onunload but I couldn't reach a clean and reliable way of doing so.
How could I develop such a system combining single-user mode and auto/smart logout at the same time?
Thanks for your help.
The only way you can achieve this is by checking whether the logged in user has been active in the last X minutes. Check this when the new user tries to log in. When the previous user has been inactive for that period, unset the status in the database and let the new user in. You should then also invalidate the session of the previous user, in case he comes back.
Don't try to detect session endings.
You could reduce the user's Session timeout. I think you can accomplish that both from Php and the Webserver (Apache, IIS, ..), should really look at the man pages. That done, you could realize a polling system which periodically ping the user to verify his/her presence. For example, you could make a client-side Ajax script which pings the site at fixed intervals, so that would prolong the user's active Session. If the user doesn't ping the site anymore, after the time-window has expired, then set his/her status = 0.
That is just an idea. Try searching more about on Google.
A variant: you could set a cookie from the server-side language, and associate the session with that cookie. So, give it a short expire time. Then make a client script which periodically send a hidden request to the server. When the server receives the request, it re-write the cookie again, so the new time will start again from the beginning.

Check if user is offline

I have an online game. I wish to show how many user are online. The problem is to know when a user is offline.
Is there a way to perform a check on sessions cookie to acknowledge whether the session with the broswer was closed?
I was thinking about simply set a timeout on the server which launch a script that count how many session cookie are present, but how do I check if the session cookie is about somebody who's logged and not just a visitor?
How did you handle this?
1) I don't want to rely on a script fired with the logout button, since nobody ever logout... people simply close the browser.
2) About timestamps and registering activity? Since in my game users interact with an svg (not moving through pages), they generate a huge amount of clicks. Making a query for each click for each of them refreshing a record would be very expensive.
When the user interacts with the site, set their last activity time.
If it is longer than 30 mins or so, you can assume they are offline.
You can also explicitly set someone to offline when they click logout.
However, your case is a little different. You could use a heartbeat style script.
Whilst they are on the page, use setInterval() to extend the expiry date, up to a maximum range (in case the user leaves their browser window open for hours on end).
Since your code gets executed when the page is loaded you cannot make a check if the user closed his browser or not.
So the common approach would be to use timestamps and update this stamp if the user does something on your site and if the timestamp is older than say 5 minutes you just assume he is offline

Detect online users?

I'm not sure what would be the easiest way to do this. I need to be able to detect what users are online on my website. So when people are viewing a thread or something it will say next to the users name if they are ONLINE or OFFLINE. And at bottom of forum index it will say all the users who are online.
What would be the easiest approach to do something like this? I'm not sure if I will need a Javascript which would run every time a page loads or what.
Thanks :)
have a MySQL database with a user table
have a column in that user table which saves the "last seen"-time
update that column on every page request
when checking for online or offline, check if current time minus "last seen"-time is greater than some treshold you like
Edit: You could optionally make a javascript "ping" the server (request an empty page) every two minutes or so if you want people idling with your Website open to be displayed as online, too.
One approach is to store your users sessions in a database or another store like memchached (or ideally both What is the best way to handle sessions for a PHP site on multiple hosts?). Then you just look up the user in your store and see if their session is still active.
A solution like this: http://pureform.wordpress.com/2009/04/08/memcache-mysql-php-session-handler/
You need to hold some kind of a "session" table, where you hold the user and the time of when they visited a page.
If the time is older then 5 minutes the user is offline (and the row can be deleted).
The other users in the session table are "online".
First thing first, there's no way to accurately get the current online users count. The best you can do is get a rough number.
Think about this situation: a user logs in to your website, clicks some links, and just closes the browser tab without logging out. Actually this is quite common. Your server never knows that a user closes the browser, so the session of that user keeps alive for some time (30 minutes maybe) if the session stored on your server.
In some stateless web apps like Ruby on Rails apps, sessions are stored completely on the browser side (in the cookies), and the server totally forgets about the user after each request, and that makes counting online users nearly impossible. This is a tradeoff for simplicity and scalability.
So how can we get such a number? We must make assumption basing on compromise. We make such an assumption that a user is online if his/her last request was made less than 30 minutes ago, then we can get the number of "online" users by tracking the timestamp of the last request each user makes. Or we can assume that a user is online if his/her session on the server is still alive, and count the sessions on the server. Either way, we have to convince ourselves that the number of "dangling sessions" is negligible (I know it's hard).

Categories