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.
Related
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).
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.
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
I have built a simple cakephp app with simple user authentication. It works. I have a problem when the user is idle for longtime, the app logs out the user. The user should log back to perform actions on the app.
My question is there is anyway I can save the time when the user was logged out.
I appreciate any help.
Thanks.
Ivanka,
what Thariama wrote seems to be quite sound. Nevertheless, if you need the feature to show the user status to others, imho you have to work with cron jobs and cake shells.
You would need:
Thariama's suggestion with the timestamps
The cake shell + cron job going over every logged in user. Once NOW - lastActionTimeStamp > maxIdleTime, log user out and persist timestamp.
Adding the second point has the benefit that other users do not see the logged out one as present/active, as it could be the case if you stick with 1. alone.
Depending on the size of your userbase, you can set the checking interval.
Another approach could be to implement some kind of client side timer (JS/AJAX) triggering a logout, which could be unreliable in nature, but should be even easier to implement.
My 2 cents.
On your server/application there will be a configuration setting which defines the idle time span after which a user gets logged out. With this knowlege (i am sure you know where to look) you are able to ddo the following
$time_span_to_logout_user = 600; // example 10 minutes
Everytime a user is logged in and requests one of your websites pages you simply store this timestamp into the db.
To get to know the loggout time you simply take this timestamp from the DB and add the $time_span_to_logout_user -> this is the user loggout time.
You can set it on app/config/core.php:
Configure::write('Session.timeout', '120');
Documentation explains this variable depends on security level.
Yes, write your own session handler and log the time using the gc and destroy fns
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
}