I am using Cakephp 1.3 and having a lot of troubles with session timeouts.
So, here's my core.php file.
Configure::write('Session.save', 'cake');
Configure::write('Session.cookie', 'TESTING');
Configure::write('Session.timeout', '0.01');
Configure::write('Session.start', true);
Configure::write('Session.checkAgent', false);
Configure::write('Security.level', 'low');
Here comes the first problem, on session.timwout it is specified as SECONDS but if I put 1 using low that gives my cookie expire of 5 hours (?). with this setting I am getting 3 minutes to cookie expire, I don't understand that, it should be 1 x 300 seconds = 5 minutes. what kind of math is that?
And the main problem is that this is not being respected, when I log to my website I can see it generated a session and will expire in 3 minutes, but as soon as I log on and click a link i get back to the log in page, which means I get de authenticated in less than 30 seconds.
I am trying to set such a low value for testing, I know high and medium security values regenerate session between requests but I would like to understand what's going on.
Thanks a lot.
Session lifetime and cookie lifetime aren't equal. Session lifetime is calculated by
Security::inactiveMins() * Configure::read('Session.timeout')
where as cookie lifetime is calculated by
Configure::read('Session.timeout') * (Security::inactiveMins() * 60)
So on a security level of low, a session timeout of 1 results in a session lifetime of 300 seconds, and a cookie lifetime of 18000 seconds, ie 5 hours.
And when using a 0.01 second timeout, session lifetime would be 3 seconds, and cookie lifetime would be 180 seconds, and therefore you are being logged out so fast.
As you've experienced for yourself, there's no need to worry about the longer cookie lifetime (which I guess is to prevent the cookie becoming invalid before the session times out, but I could be wrong on that), once the session times out, the cookie is being invalidated and finally overwritten.
Related
I am setting up the session to be valid for 4hr after login. but session is getting expired exactly at rounded hours (#12 PM, 1 AM, 2 AM so on..)
For eg: if login at 12.00 PM or 12.30PM, session is getting expired at 1 PM exactly.
Here is my code.
// server should keep session data for AT LEAST 4 hour
ini_set('session.gc_maxlifetime', 14400);
session_start();
$_SESSION['login'] = 1;
$login_session_id=session_id();
Are you on a shared server?
If so, you need to set your session directory to something other than the default /tmp/.
What happens is that if any other application on the server has a session time of less than an hour, it will expire your session data in an hour, no matter what your application's session time is set to.
This took a lot of head scratching for me to figure out, but it makes sense once you understand how PHP's session garbage collection works.
If you are actually using CakePHP then you can just set the session handler to use 'cake' instead of 'php' and this will store sessions in app/tmp/session instead of /tmp.
<?php
echo " Nfo5o " ;
set_cookie (expire, 84600);
?>
UPDATED
So I am running into another problem that I think is pretty much the same thing. I am using silex and I want the session to be stored for 5 days. I give the have the following values:
session.cookie_lifetime: 432000
session.gc_maxlifetime: 432000
session.gc_probability: 100
session.gc_divisor: 100
So from my understanding since probability and divisor are the same number, gc should happen every page load and the session file (using php native file handler for sessions) should be kept around for 432000 (60 * 60 * 24 * 5) seconds without any activity on them. This issue is even with these value, my session seems to expire between 1-2 hours of no activity.
I even tried seeting the gc_maxlifetime to 5 and that seemed to work fine so it makes me think something else is being triggered before gc_maxlifetime is.
Are there any other values I am missing?
The server decides when to clear up stale sessions.
This happens at certain times, depending on a random number and the chance you gave it (in php.ini).
Look for session.gc_divisor.
So in your situation, your cookie with the PHPSESSID is still there, and your browser sends it as it should to the server, but the server cannot find a corresponding session.
You also need to change a couple more variables in your php.ini
.check this link
I found something which I believe to be quite concerning while inspecting CodeIgniter's session handling mechanism.
$expire = $this->now - $this->sess_expiration;
$this->CI->db->where("last_activity < {$expire}");
$this->CI->db->delete($this->sess_table_name);
It appears that CI actually determines the session expiration time based on last_activity rather than a fixed, non-variable expiration field.
The problem here is that last_activity is updated to now() whenever the session is updated. So let's assume you are using CI defaults and have a session lasting 7200 seconds(2 hours) that's updated every 300 seconds(5 minutes)
The session is flagged as needing an update after 5 minutes of the last update, so if a user submits his session cookie after these 5 minutes, but before 2 hours, then CI will extend the session to last another 2 hours from this moment because last_activity will be updated to now().
This seems like a huge security risk to me, because as long as the user is active and keeps triggering the session update, its duration is extended indefinitely, effectively making the expiration setting useless. I've tested this by setting update to 10 seconds and expiration to 20. I can confirm that as long as I kept hitting refresh every 10 seconds, the session never expired!
Imagine if an attacker steals your login cookie and establishes a valid session. Even if you invalidate the login cookie, the attacker could keep his session valid indefinitely so long as he kept submitting the cookie often enough.
What do you think? Am I missing something important here? Or is this really as bad a security hole as it appears?
I think you get the point from the comments, but to simply post an answer, what you discovered is the proper function.
Sessions are ment to be 'extended' they are not created from initial fixed point in time, to + 7200 sec. Its somewhat silly if you are someone working on something and suddenly while you are active, you get logged out.
As an alternative method, if you wanted to do what you describe, you would extend the CI_Session and modify that specific method, and save it as MY_Session.
See more details here: http://codeigniter.com/user_guide/general/core_classes.html
I already made these adjustments in my php.in file and then stopped/started the server:
; 24 hour session cookie
session.cookie_lifetime = 86400
; Prevent server from cleaning up session
; Some value higher than the cookie lifetime
session.gc_maxlifetime = 200000
But that seemed to do nothing and my users are still complaining that they get logged out after about 30 minutes. And I am also getting logged out often.
What else could I look into or do in order to make my users who are logged in not to be logged out and keep them logged in at least 24 hours or more.
Thanks!
Whilst you can increase the session time out using code similar to the below: (in .htaccess, if you are on apache)
php_value session.gc_maxlifetime 86400
php_value session.gc_probability 1
php_value session.gc_divisor 100
The problem is that your sessions folder can become cluttered with inactive session files. Our sites use a half hour time out, but we have a an AJAX poller as part of the management interface which keeps the session alive once every 15 minutes. That way we only keep the session open for active users (even if they are perfoming long term operations)
Alternatively you may consider storing a separate - longer term - cookie which can be used to quickly re-establish the users session should it expire, again this prevents the need to fill your server with cumbersome session files.
What is the actual difference between session.gc_maxlifetime and session_cache_expire() ?
Suppose I want the users session to be invalid after 15 minutes of non-activity (and not 15 after it was first opened). Which one of these will help me there?
I also know I can do session_set_cookie_params() which can set the user's cookie to expire in some amount of time. However, the cookie expiring and the actual session expiring on the server side are not the same; does this also delete the session when the cookie has expired?
Another solution I have though of is simple
$_SESSION['last_time'] = time()
on every request, and comparing the session to the current time, deleting the session based on that. I was hoping there was a more "built-in" mechanism for handling this though.
Thanks.
I spent some time looking for a good answer to how the php.ini server settings make
sessions expire. I found a lot of info but it took a while to figure out why
the settings work the way they do. If you're like me, this might be helpful to you:
Sessions are stored as cookies (files on the client's pc) or server side as files
on the server. Both methods have advantages and disadvantages.
For the sessions stored on the server, three variables are used.
session.gc_probability
session.gc_divisor
session.gc_maxlifetime
(session.gc_probability/session.gc_divisor) produces the probability that the
garbage collection routine will run. When the garbage collector runs, it
checks for session files that haven't been accessed for at least session.gc_maxlifetime
and deletes them.
This is all explained pretty well in forum posts (this one especially!) - But the
following questions do come up:
1.) How is that probability applied? When does the server roll the dice?
A: The server rolls the dice every time session_start() is called during
any active session on the server. So this means you should see the garbage
collector run roughly once for every 100 times that session_start() is called
if you have the default of session.gc_probability = 1 and session.gc_divisor = 100
2.) What happens on low volume servers?
A: When session_start() is called it FIRST refreshes the session and makes the
session values available to you. This updates the time on your session file on the
server. It THEN rolls the dice and if it wins (1 out of 100 chance) it calls the garbage collector. The garbage collector then checks all session id files and sees if there are
any that are eligible for deletion.
So this means that if you are the only person on the server, your session will
never go inactive and it will appear as though changing the settings have no
effect. Let's say you change session.gc_maxlifetime to 10 and session.gc_probability
to 100. This means there is a 100% chance the garbage collector will run and it
will clear out any session files that haven't been accessed in the last 10 seconds.
If you're the only one on the server, your session will not be deleted. You need
at least 1 other active session running for yours to go inactive.
So basically, on a low volume server or at a low volume time - it could be MUCH
longer than session.gc_maxlifetime before the garbage collector actually runs and
the sessions are actually deleted. And without knowing how this works, it may
appear completely random to you.
3.) Why do they use the probability?
A: Performance. On a higher volume server you don't want the garbage collector
running on every request of session_start(). It will slow down the server
needlessly. So depending on your server volume, you may want to increase
or decrease the probability that the garbage collector runs.
I hope that this ties things together for you. If you're like me and you tried
session.gc_maxlifetime and it didn't seem to work (because you tried it
out on a development server so as not to disturb anyone), then this post
hopefully saved you some head scratching.
Good luck!
Each time session_start is called the session files timestamp (if it exists) gets updated, which is used to calculated if session.gc_maxlifetime has been exceeded.
More importantly you can't depend on a session to expire after session.gc_maxlifetime time has been exceeded.
PHP runs garbage collection on expired sessions after the current session is loaded and by using session.gc_probability and session.gc_divisor it calculates the probability that garbage collection will run. By default its a 1% probability.
If you have a low number of visitors there is a probability that an inactive user could access a session that should have expired and been deleted. If this is important to you will need to store a timestamp in the session and calculate how log a user has been inactive.
This example replaces session_start and enforces a timeout:
function my_session_start($timeout = 1440) {
ini_set('session.gc_maxlifetime', $timeout);
session_start();
if (isset($_SESSION['timeout_idle']) && $_SESSION['timeout_idle'] < time()) {
session_destroy();
session_start();
session_regenerate_id();
$_SESSION = array();
}
$_SESSION['timeout_idle'] = time() + $timeout;
}
session.gc_maxlifetime is based off of the last time a session file was modified. So every time a session file is modified or a session_start() is called in a separate page, the countdown to gc_maxlifetime begins anew and the user stays "logged in". This is the value you are looking for. You can modify this through ini_set() in your php files, or edit php.ini if you have access to it
session_cache_expire() only controls the HTTP "Expires" header. This header controls how long the downloaded page contents stay in the user's browser cache.
To check the current values, this code will be helpful:
$gc_maxlifetime = ini_get('session.gc_maxlifetime');
$gc_probability = ini_get('session.gc_probability');
$gc_divisor = ini_get('session.gc_divisor');