I want to create a page on which I can see, who is logged in on my site.
For every user after logging in I create a session, and send a query to change the row "Logged" in mysql from No to Yes.
Then, on the page I use PHP to show everyone, who has Yes set in mysql, and it works.
But, I have a problem, which occurs when someone close the browser without clicking Logout - the query doesn't execute and the Yes value in mysql stays...
What can I do to create a page like this?
Instead of having a boolean value for logged in or out, determine a reasonable amount of time for the session to expire (e.g., 1 month) and then add that amount of time to a timestamp and store that in the database as session_expires or something. Then you can check if the user's session has expired whenever you do your login checks.
Additionally, to manually expire the session (for instance if a user logs out) just set the session_expires field to a timestamp in the past.
EDIT
I didn't have access to a computer over the weekend, so I couldn't properly update my answer.
If you need to see active users, one thing I've done in the past is to use a last_seen timestamp field that updates any time the user does anything on the site. Then, on your "users logged in" page, just query for something recent like "last seen in the past 15 minutes."
You cannot do anything about that, but defining a timeout. That means your initial call after logging in that sets your customer row to "YES" should be triggered on every request (or to spare resources, every minute) to update a date column in that very customer row. If no update comes in anymore, you define that customer as "not logged in anymore" and update the column to "NO"
The fact that the user keeps on staying logged in is due to the PHP SESSION TIMEOUT which may be configured in PHP settings php.ini.
Have a look at http://php.net/manual/en/function.session-set-save-handler.php to learn how to set a session shutdown handler (that will be called once the session becomes invalid). When the shutdown handler is called, set your current session's "logged" to false in the database. Still, it may take up to 24 minutes (default value in php.ini for session timeout - session.gc_maxlifetime = 1440 minutes).
Decrease this value (session.gc_maxlifetime) to 2-3 minutes and have a ajax function on each of your pages keeping the session alive. This will definitely increase your server's load but you will definitely have a better representation of the currently active users. You can decrease the value from php.ini or by usig ini_set(‘session.gc_maxlifetime’,30); in your code.
Regards
Related
i want to calculate the time for which the user remains logged in on my site, for example if user A logs in at 10 am and logs off at 10:15 am then store 15 minutes time and if he again logs in then also calculate that time and add to this 15 minutes and shows his total time in the system.
Quick example I can give you.
First add the required field in your database. i.e. In your users table, have a field called 'totalTime' or something.
If you're using SESSIONS, keep a value $_SESSION["start_time"] when the user logs in, and when the user logs out take the difference of the current time subtracted by the start time and add it to the totalTime field in the database for the specified user.
Any variation of that should work.
You could have a loggedIn field in your table, and a totalTime field. When the user logs in, record the time in the loggedIn field. When he logs out, get the logged in time, calculate the difference, and store it in the totalTime field, and zero the loggedIn field.
If the user logs in and the loggedIn field is not zero, the user did not log out, add the difference between the current time and the last loggedIn value can be added to the totalTime (or zero added - you would decide on a policy) and the loggedIn field updated to the new log in time etc.
If you want to collect detailed information about users, and not use simple statistics that google paralytics provide, you have a couple options, none of which are perfect solutions for anything.
Option 1:
You can simply record the time when users click on your page. The issue with this is that there is no way to see how much time a user has spent on your last page. But overall it will provide a good estimate, but will be very costly if yo have over 1000 users.
Option 2:
Record the time when user enters the website, and then have javascript ajax call that will record the time when user either logs out or closes the page. This will work if you allow users to be in a single window only.
Option 3:
Have javascript execute every minute or so and tell database that user is still logged in. Almost all databases can do over 1000 queries like that per second. If you optimize it, change database engine or do anything else you can easily get to 10k-25k queries per second.
Option 3:
If you are charging people money per minute then you can wrap the entire thing in java, or flash. however it is also not very secure.
Bottom line is: There is no perfect way to do it. You will have to hope that users have javascript enabled and track their time using background scripts, or do the whole session thing and hope that users log out. Or Track everything click by click and hope that your algorithm works well enough.
The below solution would be the most efficient one
The log table should have userid, unique_identifier, start_time, end_time
Logging in to the website will add a unique identifier for that session. It can be random number of 12 digits.
A variable $default_duration = 1440; is defined to calculate the session exipry due to inactivity. This variable should be set according to your server settings. 1140 is 1140 seconds (24 minutes), which is the default session exipry time
On user login, lets say a user loggs in by 2PM, the end time is set on login as well, which will be 2.24PM. This will solve the scenario of a user's session expiry due to inactivity.
On each page load, the end time is updated with "Current Time + $default_duration"
If a user clicks on Logout button, the endtime for that session is taken from the current time. This records the exact duration of the user.
Incase if the user logout and logins again, it would have a different "unique identifier" and the log time is updated against it.
I'm working on a "flash website". In this program, I'd like to add an "Online Users" list, which relies on sessions: A session is started when a user logs in, and the user is marked as Online in the database. As soon as the logs out or closes the browser, the user is marked as Offline in the database.
I know that running some functions when the browser is closed will require Javascript, and it's not safe either: If the browser were to crash, the functions wouldn't run. That's why I've settled for the database updating if the user logs out or if the user's session times out.
I've been looking up session timeouts, and ran into this, along with many others like it marked as duplicates: How do I expire a PHP session after 30 minutes?
The problem with the answer's method is; It's a conditional sentence that checks if the user's last activity was X seconds ago, and if there was no activity, it times out. Useful in some websites, but useless for the Online Users list, since it updateds when a new request is sent, and since there won't be any requests after the user closes the browser.
Also mentioned in other answers is the use of session.gc_maxlifetime and session.cookie_lifetime, but the Best answer states that using them is a bad idea; One doesn't destroy the session, just the cookies, and the other is "cost-intensive".
What I want is the user to time out and the database to update and mark the user as Offline without using the If-Conditional sentence, or maybe with using a different If-conditional sentence that only has to be used once when the user logs in, like a timer or something, and whenever a request is sent, the timer restarts...those are just my ideas so far on how to solve this problem.
But, how do I do this? I'm sorry if the answer is something very simple and obvious, I'm very new to PHP.
Edit: Long Story Short:
I want to run a function after the user closes his browser, or is inactive for 20 minutes.
Clarification...
I want to update the database after 20 minutes of inactivity even if the browser has been closed.
I want to update the database after 20 minutes of the browser being
closed.
I don't think this is really possible to do with browsers being closed (reliably). If they click the logout button you can obviously run some code to mark the user as logged out. You can specify how long a session is good for with the functions you mentioned but all this does is makes the cookie be deleted on the client side, it doesn't trigger anything on the server side.
About the only thing you can do is track the time of the user's last activity and if they haven't had activity in a while assume they are gone. So just add a field to your user table and store a datetime or unix timestamp of their last activity. Then you can either run a cron job every few minutes that marks users as logged out or you can simply modify your SQL query to pull only users that have a last activity less than 20 minutes ago.
You can do this with the help of a online users table with last active field,
window.setInterval(function() {
$.ajax({
url: "http://yourdomain/updateLastactive/?uid=" + User_ID,
success: function(data) {
}
});
}, 5000); // 5 seconds
This page will update the current time-stamp as last active for that user
Then on online users query you can do like below,
SELECT UID FROM ONLINE_USERS WHERE LAST_ACTIVE > DATE_SUB(NOW(), INTERVAL 30 MINUTE));
if (!isset($_SESSION['CREATED'])) {
$_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
// session started more than 30 minutes ago
session_regenerate_id(true); // change session ID for the current session an invalidate old session ID
$_SESSION['CREATED'] = time(); // update creation time
}
Also read this
http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime
You want to catch the event by using the information here:
How to capture the browser window close event?
You will then need a page on the server that you call in that event handler with the sessionID.
That page calls a local script, page, or service that you set up to delay 20 minutes and expire the session. If you want to restart the clock if the user revisites before expiration, you will need to include a way to interrupt or cancel that script's process and you will need to retain the SessionID in a cookie which will need to be looked for upon every page load. If the cookie's SessionID is found and matches, the timeout gets interrupted/stopped (if it's still going). If it already completed, a new SessionID will need to be issued.
If you have a lot of these cancellations at the same time, you will instead queue them up on the server and have a process periodically check the queue and expire them as needed.
The way most sites avoid all this is to set a 30 minute or whatever session timeout that is enforced whether the visitor is active or not.
The easiest way to do this is to write a MySQL stored procedure that looks at the session timestamp and deletes the session data when it is > 20min old. You can also do it as an external cron job, but a stored procedure would be better.
In addition, you need to refresh the session timestamp every time the user connects.
If you want to make sure you don't delete a session when the user still has your 'page' open, then some background JavaScript refresh to your site will function as a keep-alive. Note that if the user closes the 'window' or 'tab', it will be the same as the whole browser being closed - I'm not sure you can do anything about this.
Of course, you to do this, you need to store your sessions in MySQL.
TL;DR
MySQL stored procedure or cron job deletes session if session_timestamp > 20min
Client-side Javascript does ajax refreshes to keep session open
Session timestamp updated every time the 'page' is requested (browser or ajax).
For example, if I want to set up a trigger that fires every hr passed since the current time, how would I implement that?
I am using PHP to write my backend code, essentially, if a user logged in, I give a sessionID, if there's no activity every hr , then session timeout. I think it needs to be implement in PHP right?
You use the cron job scheduler to run your script.
For Windows, you can try the Windows Task Scheduler. It provides similar functionality.
Actually, you don't need cron to do this.
Since you want to end the session if the user has been inactive for one hour, how about you do this.
When the user visits any page, update a $_SESSION variable with the current time.
Once the user browses to a new page, check if the current_time - last_time > 1 hour. If so, end the session and redirect them.
You should do this with cron scripts, not in PHP. Having PHP scripts running for hours is generally bad practice.
No need for job scheduling here. When you give them a session ID, store the session ID in a table in your database. Then do this upon every single request:
if session id row is found
if current time - last updated time > 1 hour
Do not allow access. Session is expired
else
update timestamp of session id row, setting it to the current time
allow access
end
end
Essentially: every time the user requests something, you can update a timestamp field in that session's row in your database. If the current time - last updated time > 1 hour, then the session is invalid and you should not allow the access.
If you wanted to schedule a job to go delete or otherwise deactivate rows that have expired, that's fine, but your session management scheme should not depend on that.
That said, if you don't have to roll your own session management, don't. It's fraught with lots of little details that are easy to overlook, and could result in leaving your site vulnerable. If you still need to roll your own, check out some of the OWASP materials about session management and authentication:
https://www.owasp.org/index.php/Session_Management_Cheat_Sheet
either, set up a cron job that runs hourly, or instead set up code that retroactively calculates what needed to be calculated since the previous visit.
it would help emmensly if you were to describe what you are trying to accomplish in more detail.
I need to delete old user datas in the DB, if user session is timeout.
How can I solve this problem with using PHP?
You can store the session_key with the rows in the database, and then define a time limit yourself. And then create a cronjob that delete's all rows with session_key's that has not been used within your limit.
A default session last until the browser is closed, so you cant know how many seconds that the session is active. Even when the session is closed, the session will not be deleted until the garbage collector removes it.
You can set the time for session time out . say 30 mins.
sesssion_gc_maxlifetime
You can check the login time of a user .
But if you want to delete the data , better to keep session in DB or at least
keep a status , login or logout and login time and logout time in the DB
It will be safe
So you can delete the data based on login time and current timedifference
set a cron job run in 30 mins or whatever time you wish
There is no way to add code to run when the session times out. You'll have to come up with a scheme yourself.
I'd suggest adding a timestamp to your database records and updating it every time the data is accessed. Then have a script via cron go through the records and delete those that are older than the session timeout.
I'm trying to log users out when the user's session timeout happens. Logging users out - in my case - requires modifying the user's "online" status in a database.
I was thinking that I might be able to use the observer pattern to make something that would monitor the state of the user session and trigger a callback when the session expires - which would preserve the user's name so we can update the db. I'm not exactly sure where to begin on the session side. Can I tie a callback to the session's timeout?
are these things built into any available pear or zend session packages? I will use whatever I have to to make this happen!
UPDATE # 16:33:
What if you have a system where users can interact with each other (but they can only interact with online users)? The user needs to know which other users are online currently.
If we simply check to see if the session is still alive on each page refresh, then after a timeout, the user is sent to a non-logged in page, but they are still listed as online in the system.
That method would be fine except that when we timeout the session, we lose the information about the user which could be used to log them out.
UPDATE #16:56:
right. Thanks. I agree...sort of ugly. I already have some slow polling of the server happening, so it would be quite easy to implement that method. It just seems like such a useful feature for a session handling package. Zend and PEAR both have session packages.
Take the simplest case first. Suppose you have 1 user on your system, and you want their session to timeout, and you want accurate reporting of their status. The user has not been to a page in 12 minutes, and your session timeout is set to 10 minutes. One of two things will happen. Either they will visit again in a short while, or they will not. If they don't visit again, how will the system ever run code to update their timeout status? The only way* is to have a separate process initiate a status update function for all users who are currently in status "in session".
Every time a user hits your site, update a variable in the database that relates their session to the last accessed time. Then create a cron job that runs every minute. It calls a simple function to check session statuses. Any sessions older than the timeout period are set to status "timed out". (You should also clean up the table after timed out sessions have sat for a while). If you ever want a report on the number of people logged in, query for all records that have a last accessed time later than the timeout interval start.
"*" There are other ways, but for the purposes of a simple web application, it's not really necessary. If you have something more complex than a simple web app, update your question to reflect the specific need.
Whenever a user hits a page, mark that time in the database, call this column LastAccessed. When the user clicks on the Logout portion of your site, you can set this value to null. When writing your query to find a list of users who are currently logged in, do the following:
SELECT * FROM Users WHERE LoggedIn=1 AND LastAccess > DATEADD(Minute,-20.GETDATE())
Which would return the users who still have an active session. Pardon the SQL which probably doesn't work with MySQL/PHP, but this should give you a general idea.
Why do you want to do this? The common approach is to check on every request sent by the user if the timeout has expired. Of course that means that the status in your db is not up to date, because the user is still shown as logged in, even though the timeout has been reached.
But for practical purposes that usually doesn't matter.
Ugly but maybe workable suggestion:
Add an asynchronous keep-alive requester to pages, that updates their last-active timestamp. You can then have a cron job that marks users as offline if they have a last-active timestamp more than 20 seconds old. Setting that cron job to run every minute would do the trick. I'm not sure there's a way to trigger something to happen when a user's session times-out, or closes their browser.
My first thought is that you could create a custom session handler that interprets being logged in as having an active session.
For some examples on creating a custom session handler see http://www.daniweb.com/code/snippet43.html and read the PHP doc http://ca.php.net/manual/en/function.session-set-save-handler.php
I know this might be a older question but the "best" answer to your question is found here:
http://www.codeguru.com/forum/archive/index.php/t-372050.html
Here is what it says:
The php.ini file contains a setting called sesison.save_path, this determines where PHP puts files which contain the session data. Once a session has become stale, it will be deleted by PHP during the next garbage collection. Hence, a test for the presence of a fiel for that session should be adequate to determine whether the session is still valid.
$session_id = 'session_id';
$save_path = ini_get('session.save_path');
if (! $save_path) {
$save_path = '.'; // if this vlaue is blank, it defaults to the current directory
}
if (file_exists($save_path . '/sess_' $session_id)) {
unlink($session_id); // or whatever your file is called
}