I have a login page/system which has worked correctly for years, leaving the user logged in until he/she either closes the browser window or logs out manually. But lately (starting yesterday) after only a few minutes of inactivity the session cookie/s seems to expire, causing the user to be logged out automatically.
This happens on different browsers and different operating systems, the PHP version is 5.6.29, which has been changed recently (before it was 5.5 and even 5.3).
I create and refresh the session on every page with session_start(). The login script first checks user name and PW and also gets some other user data from the database. These other data are first saved in variables and then written into session variables like
$_SESSION['username'] = $name;
$_SESSION['usertype'] = $type;
The successful login state is saved like this:
$_SESSION['login'] = "ok";
On the other pages I check the login state like this:
session_start();
if(($_SESSION['login'] != "ok") OR ($_SESSION['usertype'] != "xxx")) {
header("Location: ../login.php"); /* redirects to login page if conditions are not true */
exit;
}
The login works, and logged-in users can proceed to other pages as long as the do it more or less in constant succession, but if someone waits a few minutes before proceding (i.e. without any acitivity), he/she is logged out (i.e. redirected to the login page when trying to open another page).
To make it extra-nasty, half of the time it just works as expected, also after half an hour...
Any help would be very much appreciated.
UPDATE:
Adding ini_set('session.gc_maxlifetime', 3600'); and `ini_set('session.cookie_lifetime', 3600); didn't help. I removed it again.
After that I had a look in the error logs and found this:
ap_pass_brigade failed with error 103: Software caused connection
abort
(problem is, I don't have access to the server settings - this is on a shared webspace...)
You can see the php configuration (php.ini) by phpinfo();
<?php
phpinfo();
Check the session.gc_maxlifetime values first then if you need to set it see the following ways.
You can set it with .htaccess file if you don't have permission for edit the php.ini file.
.htaccess
<IfModule mod_php5.c>
php_value session.cookie_lifetime 3600
php_value session.gc_maxlifetime 3600
</IfModule>
Even you can set it by ini_set();
<?php
ini_set('session.gc_maxlifetime', 3600);
For anyone who is interested: The session didn't actually expire, but the session variables disappeared (and reappeared again randomly).
This is discussed in a follow-up question I posted here:
php $_SESSION variables disappear and reappear randomly
You must have changed the session.name from default PHPSESSID to something else. Keep its default value session.name = PHPSESSID. Everything will be OK.
It's a PHP bug.
Related
I have a site where I use session authorization for my users
Details are:
PHP Version 7.2.8
session.gc_maxlifetime 604800
session.gc_probability 1
session.gc_divisor 1000
I use the following db.php file for creating a session
$dinamo_session = session_name("dinamo_session");
ini_set('session.cookie_domain', '.DOMAIN_NAME');
#if (isset($_REQUEST[session_name("dinamo_session")])) {
#ini_set('session.cookie_lifetime', 604800);
#ini_set('session.gc-maxlifetime', 604800);
#ini_set('session.save_path', '/var/www/user9357/data/_SESSIONS');
session_start();
#session_regenerate_id(true);
#session_write_close();
#}
My users do not complain from their end everything seems to be ok, the only thing is that I see a growing amount of session files with zero sizes (as well as I see normal session files with the real session's data)
You can see different lines of code are commented out. I tried to use all of them to avoid creation of these zero size files but that did not help (isset - to check if the session has been created before, session_regenerate_id(true) - to delete the old files) but no luck. I even had to comment out isset as some users complained that they were not able to log in. I also checked that: Opera and Firefox were ok, but Vivaldi browser was not able to login
Any ideas why these zero files are created and how can I stop it?
I have a site running on apache and using php. Sometimes I have users on the site doing work and then they suddenly lose their session. I start the session with
session_start()
and it puts a PHPSESSID cookie in the user's browser. I also have
session.cookie_lifetime=0
in my php.ini file. I also do a javascript long poll every 5 minutes to see if the session is still active.
Here is the php code that I use to see if the session is still active
public function actionPollLogin()
{
if (isset($_SESSION['user']['id']))
{
echo $this->renderAjaxJson(array("success"=>1));
} else {
echo $this->renderAjaxJson(array("success"=>0));
}
}
If success == 0 then I return the user to the public part of the site. But like I said, the weird thing is that the user can be actively using the site and then idle for 20 seconds and get logged out. And for testing, I dump the session to the screen that the users are returned to confirm the session is dead.
What settings to I need to tweak to allow active users to stay logged in.
Here are my current php.ini settings
session.hash_bits_pre_character=5
session.hash_function=0
session.cache_expire=180
session.cache_limiter=nocache
session.referer_check=
session.gc_maxlifetime=1440
session.gc_divisor=1000
session.gc_probability=1
session.serialize_handler=php
session.cookie_httponly=
session.cookie_domain=
session.cookie_path=/
session.cookie_lifetime=0
session.auto_start=0
session.name=PHPSESSID
session.use_only_cookies=1
session.use_cookies=1
session.use_strict_mode=0
Docs
session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up.
So after 24 minutes your sessions expire server-side and are potentially cleaned up.
The solution for me was to add this line after my session_start();
$_SESSION['activity']=time();
This updated the last modified date of the session file everytime the user interacted with the site.
I'm using a java based uploading construct http://www.javaatwork.com/java-upload-applet/details.html that I tried running over night.
It basically stores everything on the server's hard drive (/var/www/private/$userId)
Makes sure that data is well-formed
Then passes it onto a permanent storage (Amazon S3).
After step 1 completes, I run the following code:
if($_SESSION['userId'])
{//Makes sure that data is well-formed}
else
{echo 'you are not logged in';}
I tried running this for four hours only to find you are not logged in printed to the screen.
Here are the appropriate directives in the cgi php.ini file (I'm using ubuntu 12.04 with apache2.)
session.gc_probability = 0
session.gc_divisor = 1000
session.gc_maxlifetime = 14400 //this is 30 hours, which is far greater than the 4 hours it was running
session.cache_expire = 1800
session.cookie_lifetime = 0
Most of these directives are the default with exception to session.gc_probability and session.gc_maxlifetime.
I was trying to resolve this issue and came across a really helpful blog by Jeff from which I inferred that browsers can cause the PHPSESSID cookie stored in the browser to be deleted if a period of inactivity on the website from within the browser occurs. He suggests
"Create a background JavaScript process in the browser that sends regular heartbeats to the server. Regenerate a new cookie with timed expiration, say, every 5 or 10 minutes."
http://www.codinghorror.com/blog/2008/04/your-session-has-timed-out.html
So I decided to do just that.
function myTimeoutFunction()
{
$.ajax({
url: "heartbeat.php",
success: function() {
}
});
setTimeout(myTimeoutFunction, 15*60*1000);
}
myTimeoutFunction();
heartbeat.php
<?php session_start(); ?>
I'm about to test this for an upload that should take ~4 hours. However I just read the following
In general you can say session.gc_maxlifetime specifies the maximum lifetime since the last change of your session data (not the last time session_start was called)
https://stackoverflow.com/a/1516338/784637
If I had 3 session variables, $_SESSION['userId'] $_SESSION['firstName'] $_SESSION['lastName'], would I need to reset all their values in heartbeat.php
session_start();
$_SESSION['userId'] = $_SESSION['userId'];
$_SESSION['firstName'] = $_SESSION['firstName'];
$_SESSION['lastName'] = $_SESSION['lastName'];
Or could I just reset one value
session_start();
$_SESSION['lastHeartbeat'] = time();
so that the other three would not expire?
The PHP session is kept as a whole; any changes in $_SESSION will update the change time and, by extensions, preserve the entire session.
Concerning the actual issue: PHP shouldn't GC sessions until the max time is reached, but that doesn't mean PHP is always clearing it. By default, sessions are kept in the /tmp (or another) directory and some Linux distros will have cron jobs that may clean the folder out from time to tome. Check for crons or other things that may clear the sessions independent of PHP too.
I was working in a project where another developer wrote the code,while a user is login the session_start() as usual and then he is cheking like belows:
if($a['userName'] == $username && $a['password'] == $pwd)
{
$_SESSION['id'] = $a['id']; ?> <script language="javascript"type="text/javascript">window.location="host.php";</script> } else {
$msg= "Invalid Username Password";
}
And when a user want to use the form after couple of seconds its logout and user can not submit data.
I have tried increasing session life time duration:
$sessionCookieExpireTime=8*60*60;
session_set_cookie_params($sessionCookieExpireTime);
And also tried with increasing session lifetime in runtime like below:
ini_set('session.gc_maxlifetime', '3600');
And finally tried by increasing php.ini session lifetime .
Unfortunately those did not work.
One thing I should mention that,there is no session_destroy() for logout issues.
Thanks in advance.
What kind of server are you working on?
On a shared server that runs multiple sites that use a shared session directory the session.gc_maxlifetime is in effect the shortest lifetime of all sites accessing that shared directory.
If the problem is on a development server, find out where the session files are stored and look at what happens to them.
It is also possible that the directory where the sessions are stored is not writeable. In that case the session variable is never stored in the first place.
In all three cases: try to store the session files in a different directory. In code you have to set the session directory with session_save_path() before you call session_start().
The timeout occurs when user idle activity for certain time. There is no way to logout automatically unless using session_destroy.
It may be possible that your code
$a['id'];
returns null by chance.
Also, you need to checkout which page is getting logged out.
Giving the full code may be easy to identify the issue.
I have a site with both public and private sections. To access the private areas, users have to log in, which sets session variables. The login script authenticates everything and then changes the header location to the private page:
//get info from database and if user is authorized, then redirect
session_start();
$_SESSION['authorized'] = $user;
$_SESSION['firstname'] = $first;
$_SESSION['lastname'] = $last;
$_SESSION['password'] = $pass;
$_SESSION['position'] = $position;
$_SESSION['email'] = $email;
header( "Location: index2.php" );
Then on the index2.php page, I have an authorization check at the top:
session_start();
if(!isset($_SESSION['authorized'])){
header( "Location: denied_unauth.php" );
die();
}else{
//rest of page
Everything works like a charm. EXCEPT...if there's no activity for 20 minutes, users have to log back in. Index2.php uses jQuery to load divs into it, so users never leave index2.php. If they click to retrieve a page on the private site after inactivity, instead of the div they requested, they get a "logged out" message and are presented with the login form again. It's the exact same script as the one listed above, setting the exact same session variables and redirecting them back to the exact same page (index2.php), which is the same page they're logging in from - basically, just reloading the page.
Whenever I test this, index2.php isn't recognizing the new session. It's sending users to "denied_unauth.php" every time. This tells me that the login script is working, it's recognizing the username and password and sending users to index2.php...but when the page reloads index2.php, the session isn't being recognized. I even tried adding a random number to the end of the URL "index2.php?somerandomnumber in case it was a caching problem, but it didn't help.
Any ideas?
EDIT: To be clear, I'm not asking for a way to STOP the user being logged out. I'm trying to figure out why, if new session variables are created during the log-back-in script, it's not recognizing them when reloading the page. The session variables ARE created the first time they log in, so I know that part of the script works. But when they go back to the page again after re-logging, it doesn't recognize the new $_SESSION['authorized'].
EDIT 2: Here's what is happening:
From the page index.php, user logs in. The login form creates a session and redirects the header to index2.php
Page index2.php checks whether session is set, if not it kicks the user out to a "denied access" page.
User clicks links within index2.php page to load sections into the main div
Each file that loads into the main div has a check on it to see if the session is set. If the session exists then the file loads, if the session is expired then instead of the file, it shows the user the login form and asks them to log back in. (all this works so far)
When the user logs back in from this form, a new set of session variables is created. I have tried both setting a new session or session_regenerate_id() and neither seems to work.
This new session is NOT being recognized by index2.php and it kicks them out every time. I have tried both redirecting straight to index2.php after login, or simply loading the div they'd requested in the first place, but both ways, index2.php doesn't see that the session is set and the user ends up on the "denied access" page.
Sessions have a timeout specified in the php.ini file:
; Lifetime in seconds of cookie or, if 0, until browser is restarted.
session.cookie_lifetime = 0
; After this number of seconds, stored data will be seen as 'garbage' and
; cleaned up by the garbage collection process.
session.gc_maxlifetime = 1440
; Document expires after n minutes.
session.cache_expire = 180
If you cannot or do not want to change that globally on the server, try using an .htaccess file on Apache.
I'm not sure it will work, but if you don't have access to your php.ini or .htaccess file,
you might wanna use this after your session_start():
session_regenerate_id(true);
You should also put this in the page your jquery is loading divs from.
One surefire way to deal with this is to create an ajax heartbeat script you load in the background every X minutes which only needs to "touch" the session. This expects all your users to have JavaScript enabled though.
It's a session lifetime problem. you can solve this problem two way. here the description:
change the php.ini file. increase the session.gc_maxlifetime, by default it is 1440 that means 24 mins. you can increase this by second.
Here the second way without change the php.ini file. you can set session lifetime with php by using the following code :
ini_set('session.gc_maxlifetime', 30*60);
session_start();
I finally figured it out and got it to work. The login form was bound to a jQuery call on submit, I changed it so that the new login form actually performs the post call...and it started working.