I'm having an issue with session variables becoming null after about 35-40 minutes. However, the session ID appears to still show as valid (and the same number as it was before).
I've created some testing code which reads and displays the session variables and then reloads the page after an increasing number of seconds. It works until it gets to 2400 seconds, at which point the variables are null on next display. In other words, it's always null when it waits 2400 seconds between refresh. I've set the session.gc_maxlifetime in .htaccess to 7800 (and it's apparently set because it reads as 7800 with ini_get).
I'm either missing something obvious or some serious strangeness is at work here. This is driving me nuts.
This is on a Linux VPS with WHM.
Code to create the test session:
<?php
// start session
session_start();
// set session value
$_SESSION["session_memberid"] = 1234567;
$_SESSION["session_refresh"] = 2000;
// write file, close
session_write_close();
// display confirmation
echo json_encode(array(
'$_SESSION["session_memberid"]' => $_SESSION["session_memberid"],
'session_id' => session_id(),
'maxlifetime' => ini_get('session.gc_maxlifetime')
));
?>
Code to read the session (is reloaded automatically):
<?php
// start session
session_start();
// get session id
$session_id = session_id();
// get stored memberid
$member_id = $_SESSION['session_memberid'];
$_SESSION['session_memberid'] = $member_id;
// get last activity
$lastactivity = $_SESSION["last_activity"];
// increasing refresh time
$refresh = $_SESSION["session_refresh"];
$_SESSION["session_refresh"] = $refresh + 100;
// update time
$_SESSION["last_activity"] = time();
// write file, close
session_write_close();
...
(code to display and refresh variables)
Output when valid read:
{"memberid":1234567,"session_id":"c9d20d4992f184f29b259ef5ccab275f","sessionpath":"\/tmp","maxlifetime":"7800","sessioncookiepath":"\/","sessioncookielifetime":"0","referrer":"","autostart":"0","cache":false,"time":1365004882,"cookie":{"lifetime":0,"path":"\/","domain":"","secure":false,"httponly":false},"refresh":2400}
Output when invalid read shows memberid (the variable that we need), time (last_activity) and refresh time as null.
Any ideas?
Is it possible that the apache user doesn't have permissions to write in the /tmp directory, and the session is only active in ram for that time period. Once expunged out of ram, it would default to the file, which never got written to because of permissions?
As it turns out, the issue was that php.ini wasn't correctly being overridden by settings in .htaccess or ini_set at runtime, even though ini_get showed the value as overridden. The reason isn't clear but the working fix has been to simply change the session.gc_maxlifetime in the php.ini.
Related
I just use Session Variables in my code. I do not start any activity with cookies. I just do session_start() and do the manipulation of the variables.
But at the end of some time (about 30 minutes) the session goes down. If I do print_r ($ _ SESSION) the session is in void.
I've tried set session.gc_maxlifetime to 7200 (2 hours), but the session is destroyed in less than 30 minutes again.
How can I resolve this? It's normal? Should the session not only be destroyed if I close the browser or give the statement/instruction to session_destroy?
The default timeout is 24 minutes.
Other than php.ini, you can change it in code. You could try this:
// server should keep session data for AT LEAST 1 hour
ini_set('session.gc_maxlifetime', 3600);
// each client should remember their session id for EXACTLY 1 hour
session_set_cookie_params(3600);
session_start(); // ready to go!
from this answer: How to change the session timeout in PHP?
An article on it:
https://bytes.com/topic/php/insights/889606-setting-timeout-php-sessions
which gives code that I've adapted to 2 hours.
session_start();
$timeout = 7200; // Number of seconds until it times out.
// Check if the timeout field exists.
if(isset($_SESSION['timeout'])) {
// See if the number of seconds since the last
// visit is larger than the timeout period.
$duration = time() - (int)$_SESSION['timeout'];
if($duration > $timeout) {
// Destroy the session and restart it.
session_destroy();
session_start();
}
}
// Update the timout field with the current time.
$_SESSION['timeout'] = time();
php.net page on it:
http://php.net/manual/en/function.session-set-cookie-params.php
Other stack answers verify this (some highly rated):
PHP sessions default timeout
How do I expire a PHP session after 30 minutes?
Session variables are meant to hold information until the browser is closed. I am not quite sure what you want to achieve in your project, since you have not posted any code.
Something simple like not putting session_write_close(); at the end of your php script or session_start() at the very beginning, before any html tags could be messing your code.
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.
How to set session lifetime in PHP? I Want to set it to forever as long as the request is exist. The request is AJAX. My PHP code that handle AJAX request is:
// AJAX.php
<?php
session_start();
$_SESSION['counter'] = $_SESSION['counter'] + 1;
header('Content-type: application/json');
echo json_encode(array('tick' => $_SESSION['counter']));
?>
and the JavaScript:
$(document).ready(function() {
function check() {
getJSON('ajax.php');
}
function getJSON(url) {
return $.getJSON(
url,
function(data) {
$("#ticker").html(data.tick);
}
);
}
setInterval(function() {
check();
}, 10000); // Tick every 10 seconds
});
The session always resets after 300 seconds.
The sessions on PHP works with a Cookie type session, while on server-side the session information is constantly deleted.
For set the time life in php, you can use the function session_set_cookie_params, before the session_start:
session_set_cookie_params(3600,"/");
session_start();
For ex, 3600 seconds is one hour, for 2 hours 3600*2 = 7200.
But it is session cookie, the browser can expire it by itself, if you want to save large time sessions (like remember login), you need to save the data in the server and a standard cookie in the client side.
You can have a Table "Sessions":
session_id int
session_hash varchar(20)
session_data text
And validating a Cookie, you save the "session id" and the "hash" (for security) on client side, and you can save the session's data on the server side, ex:
On login:
setcookie('sessid', $sessionid, 604800); // One week or seven days
setcookie('sesshash', $sessionhash, 604800); // One week or seven days
// And save the session data:
saveSessionData($sessionid, $sessionhash, serialize($_SESSION)); // saveSessionData is your function
If the user return:
if (isset($_COOKIE['sessid'])) {
if (valide_session($_COOKIE['sessid'], $_COOKIE['sesshash'])) {
$_SESSION = unserialize(get_session_data($_COOKIE['sessid']));
} else {
// Dont validate the hash, possible session falsification
}
}
Obviously, save all session/cookies calls, before sending data.
Set following php parameters to same value in seconds:
session.cookie_lifetime
session.gc_maxlifetime
in php.ini, .htaccess or for example with
ini_set('session.cookie_lifetime', 86400);
ini_set('session.gc_maxlifetime', 86400);
for a day.
Links:
http://www.php.net/manual/en/session.configuration.php
http://www.php.net/manual/en/function.ini-set.php
Prior to PHP 7, the session_start() function did not directly accept any configuration options. Now you can do it this way
<?php
// This sends a persistent cookie that lasts a day.
session_start([
'cookie_lifetime' => 86400,
]);
?>
Reference: https://php.net/manual/en/function.session-start.php#example-5976
Sessions can be configured in your php.ini file or in your .htaccess file. Have a look at the PHP session documentation.
What you basically want to do is look for the line session.cookie_lifetime in php.ini and make it's value is 0 so that the session cookie is valid until the browser is closed. If you can't edit that file, you could add php_value session.cookie_lifetime 0 to your .htaccess file.
Since most sessions are stored in a COOKIE (as per the above comments and solutions) it is important to make sure the COOKIE is flagged as a SECURE one (front C#):
myHttpOnlyCookie.HttpOnly = true;
and/or vie php.ini (default TRUE since php 5.3):
session.cookie_httponly = True
I dont see this mentioned anywhere, but setting ini_set('session.gc_maxlifetime', $max_lifetime); in the PHP file itself is usually not going to have the desired affect if the php.ini file has a LOWER value and the server hosts multiple domains/vhosts. If you have User on X website, and the maxlifetime is set to 10 seconds (not a real value, this is just for example) in the PHP file and then have the maxlifetime set to 5 in php.ini something interesting/unexpected will happen if you have multiple domains/vhosts.
When a 2nd user visits a site that HASNT set ini_set('session.gc_maxlifetime', $max_lifetime); in it's PHP file and it defaults to whatever php.ini has, that will cause PHP's garbage collection to fire using 5 seconds rather than 10 seconds as maxlifetime, thus deleting the user's session which was supposed to last at least 10 seconds.
Therefore, this setting should almost NEVER go in the PHP file itself and should actually be in the vhost entry if your setup has this capability and falls into this type of scenario. The only exception to this is if your server only hosts 1 website/vhost who's PHP files will always override whatever php.ini has.
This happens because all sites use the same tmp dir to store session data. Another mitigation solution would be to set the session tmp dir per vhost. And yet another (not recommended) solution is to simply disable session.cookie_lifetime completely in php.ini by setting it to 0.
As long as the User does not delete their cookies or close their browser, the session should stay in existence.
in my program for a security purpose it is neccessary to destroy the session variable if the application exceed more than its idle time.For This i am using this code,
// set timeout period in seconds
$inactive = 300;
// check to see if
$_SESSION['timeout'] is set
if(isset($_SESSION['timeout']) ) {
$session_life = time() -
$_SESSION['start']; if($session_life
$inactive)
{ session_destroy(); header("Location: logout.php"); } }
$_SESSION['timeout'] = time();
But this code refresh the session variable every 5 min, i want to know how to destroy the session variable if the system is in the idle time. And also please tell me it create any other problem if i destroy the session variable . Thanks in advance
session_unset
#Edit:
Since the session data are considered garbage after the session timed out, no action should be needed really. It should be sufficient, to make sure, the garbage is cleared in a regular manner. So simply calling a page which creates a dummy session (once a minute fe.) should be enough. The garbage collector frequency may also be configured in php.ini.
However, you can verify this easily by monitoring your sessions (in file / database / memory).
Try this:
Edit php.ini - set session.cookie_lifetime with the intended value in seconds (300 seconds for your 5 minutes).
Restart your apache server.
Login
Test the session variable after 5 minutes (should have expired).
Remember, from the docs:
The default "0" value means that the cookie stays alive until the browser is closed. This is also the default value, if not set in php.ini.
So, you must set it: it defaults to zero - so it will never expire unless someone closes the browser window.
I'm using PHP5 here. I have made a login system that check's the username and password against the records in the database. I want to use sessions to store the logged value. For example, when I reach the zone where I "log in" the user succesfully:
if($errors = 0) {
$_SESSION['logged'] = "1";
}
The problem is that I want the $_SESSION['logged'] to stay active for let's say 5 minutes so when I do a if($_SESSION['logged'] == "1") after this time to return false. Also, I would like to delete this session after the user closes the browser. Basically, I want a session configuration so that the user can safely leave his desk and when him or somebody presses refresh after 10 minutes or enters again after the browser has been closed, the session to be already removed, and the access to be restricted.
Can anybody help? Thanks.
Use session_set_cookie_params() to change the lifetime of the session cookie. Note that by default, it is set to 0 which means that the cookie is set until the user exits the browser. You can do this in the following way:
/* Set to 0 if you want the session
cookie to be set until the user closes
the browser. Use time() + seconds
otherwise. */
session_set_cookie_params(0);
session_start();
Then check for the last activity time, updated each time someone visits a page.
if(($_SESSION['lastActivity'] + 300) < time()) {
// timeout, destroy the session.
session_destroy();
unset($_SESSION);
die('Timeout!');
} else {
$_SESSION['lastActivity'] = time();
}
Instead of setting it to one, why don't you set $_SESSION['logged_time'] = time(); and then check the time against time() in your application?
If you'd like to actually expire the entire session, the exact specifics can change depending on your session handler, but for the default session handler (and any other well behaved session handler) you'll want to check out http://us3.php.net/manual/en/session.configuration.php
You can change the configuration setting session.cookie_lifetime, e.g. in php.ini or a .htaccess file:
session.cookie_lifetime specifies the
lifetime of the cookie in seconds
which is sent to the browser. The
value 0 means "until the browser is
closed." Defaults to 0.
This means (I think) that you can't have both expiry based on a timeout and expiry when the browser is closed. So maybe the best bet is to keep the default and set your own timer in $_SESSION as others have suggested, thus rendering this answer pointless.
Sessions stay alive aslong as the user stays on your site. You will have to use cookies to set a specific timeout.