I need a php code that will run a query after a specific session is going to expire,
if(!isset($_SESSION['test'])) query;
something like that but does work with session expire.
The problem you'll run into: a session doesn't just expire by itself, a session is expired on the next page load if the user waited too long. As there's no communication between browser and server between requests (user action), the server won't know if e.g. the user just closed the browser (or is doing the dishes while the website remains open).
So I guess there's nothing wrong with your code as it'll tell you if the sessin is expired on the next pageload (as long as there is a next pageload :)).
If you really need to make sure, the query runs after a session expired, I guess you'll have to save your sessions to a database and run a "cleanup"-script on each pageload to run your query and get rid of expired sessions. (e.g. save "lastUserAction" and compare that to whatever your session-limit is)
I would suggest to save the date you created the session in the database and check if the session expires like:
if($db->checkExpiredSession('test') == true) {
$db->query('...');
}
Just a thought.
Related
I have php login page that stores the user id in the session once the login is successful. User can navigate to different pages or can even close the page briefly and once user re-open the page, he is still logged in. However the problem is that when the user closes the page for longer time, the session get expired automatically and he has to re-enter the credentials and login again.
How can I keep the user logged in forever and log out ONLY if user decides to do so?
I would like the user to be able to close the page, turn off the pc for weeks and when he or she comes back to visit the page, he or she should be already logged in.
Sound like you need to set the cookie expiration date - as per this wikipedia article on HTTP cookies, if you do not set an expiration date for a cookie it becomes a session cookie. i.e. it expires once the browser closes.
There is no real way to specify that a cookie NEVER expires, however you can set the expiration date for some time far in the future.. i.e. in 10 years, and renew that expiration date every time the user loads a page.
setCookie( name, value, expiration )
Another alternative (which would also require some JS on your pages) would be to use the browser's internal database to store the user session id so that you can retrieve the session from your database (I assume you are using some sort of database, otherwise you will run into other issues as explained below).
If I wanted to achieve this I would probably have a piece of javascript on my page loads that checked for the existence of the session cookie, and if not, I would load the session id from the browser's database, drop the cookie, and force a page reload. There are certainly more elegant ways of achieving this, but this should give you an example of how to get this started.
Lastly, please keep in mind that if you don't use a database (i.e. Redis, Memcached, SQL), all you session information is lost when you restart your application server. This is certainly suboptimal, and you should store session information in a database if you want to have this information survive server restarts (or if you have a load balanced environment).
Hope this helps!
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 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).
I have a descent set up going for a user logging in and theres a session time() and a few other things added to a table.
The issue i have is that when the user closes the browser it dosent delete the session from the mysql table.
From the users perspective its fine because they have to login again when they open the browser.
But for the super-users dashboard it still shows the user is logged in if they close the browser.
I did have a look at the close browser alert javascript code but i would rather find a way doing it without that.
I then thought maybe a cron script but that could log a user out unless i was updating the time() each time they clicked another page. Is that the only way?
I wouldn't trust the browser telling you it was closing.
The only way is to do it on the server.
Try recording the current time against the session every time it gets validated - this will be the sessions last access time.
Then you can remove all sessions that exceed some time period you've decided on. You can either do this via a cron job, or add it to the session validation code and every user can help keep the table tidy.
can your database not have a "isLoggedIn" column. Can it just have a "lastActivityTime" column. The user is logged out if currentTime - lastActivityTime < loggedOutTime
I have built a session library, and I am having a very random bug (I don't really know how to unit test this, so I just filled everything with log messages and waited till it happened again) that translates into a user being logged out, due to a session ID mismatch.
The flow of the application goes like this:
A request with a valid session ID is made
Session data is found for that session ID in the DB
The 'last activity' happens to be old, so it is regenerated and updated in the DB
The new session ID is sent in the response (as a cookie)
This works fine almost always, but sometimes the next request fails to match the session ID, because (this is my guess) it was sent after we updated the database (in the previous request, which was still running), but before the response with the new cookie came in.
Did I misunderstand the concept of regenerating a session ID? I'm regenerating session ID's only for security reasons, so someone that chose to be logged in for a year, still has his session ID changed from time to time.
One option would be to keep multiple session ids per user, but put expiry times on them - when it's time to regenerate a session id, add the new one, and put an expiry time on the old one equal to some reasonable period of time (a minute, perhaps). Keep accepting the old one in addition to the new one until the old one expires.
I assume you're using session_set_save_handler(), right..? If so, try doing the following:
session_regenerate_id($delete_old_session = true);
session_write_close();
Or even:
session_regenerate_id($delete_old_session = false);
session_write_close();
Calling session_write_close() should effectively save the new session data. You only have to pay attention when you call this (usually before privilege changes > redirects), since it ends the session.
End the current session and store
session data.
Session data is usually stored after
your script terminated without the
need to call session_write_close(),
but as session data is locked to
prevent concurrent writes only one
script may operate on a session at any
time.