How often does a PHP session ID change per user? - php

Just a basic question, if you open a session when a user visits the main page and you store the session id. When would that user return say another day/time and the id be different?

this depends on how the PHP is configured. specifically these settings control how often a php session id is "erased" by garbage collector:
http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime
session.gc_maxlifetime specifies the number of seconds after which
data will be seen as 'garbage' and potentially cleaned up. Garbage
collection may occur during session start (depending on
session.gc_probability and session.gc_divisor).
http://php.net/manual/en/session.configuration.php#ini.session.gc-divisor
session.gc_divisor coupled with session.gc_probability defines the
probability that the gc (garbage collection) process is started on
every session initialization. The probability is calculated by using
gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that
the GC process starts on each request. session.gc_divisor defaults to
100.
http://php.net/manual/en/session.configuration.php#ini.session.gc-probability
session.gc_probability in conjunction with session.gc_divisor is used
to manage probability that the gc (garbage collection) routine is
started. Defaults to 1. See session.gc_divisor for details.
As far as i know the default php session.gc_maxlifetime is 1440 seconds (24 minutes). The more visits you have in your site the most "accurate" these statistics are since all this algorithm will run more often.
A tricky edge case: if you start a session and then NEVER get any other visit to your site, the garbage collector algorithm will never run, hence the session will never expire! If you can understand this, i think you have understood this answer.

Related

Is setting session.gc_probability and session.gc_divisor equal to 100% a bad idea?

The scenario:
User logs in
Cookie is set to length of session
After 1 hour of inactivity I wish to log out the user
How I think I can solve this:
Set the session.gc_maxlifetime to 1 hour (3600)
Set the session.gc_probability to 1
Set the session.gc_divisor to 1
Therefore having a 100% certainty that garbage collection will occur on any idle session cookies after 1 hour.
My question:
All the posts and documentation I've read has never mentioned setting a gc change of 100%, therefore is it bad to do this? Is there a better way?
It's a symfony app, and long term I would like to do something like this http://symfony.com/doc/master/components/http_foundation/session_configuration.html#session-meta-data but for now I was hoping to just do something simple with session.gc_*
One post I read implies that having a 100% garbage collection chance is "cost-intensive" How do I expire a PHP session after 30 minutes? is this true? If so, how cost intensive?
Cheers!
The gc_probability and gc_divisor are there to let you define the "probability" of firing up the garbage collection (GC).
Since GC (as everything) comes with a cost, you wouldn't usually want it to run on each and every web request processed by your server - that would mean that every page opening or every AJAX request served from PHP would cause the GC to run.
So, depending on the actual server load and usage, the admin is expected to do an educated guess on how often should GC be run: once in 100, 1/10000 or 1 in million requests.
But, there's a problematic flaw in the OP's original reasoning - that garbage collection will occur on any idle session. The way I read the manual, the garbage collection will occur on ANY session, not just idle ones:
session.gc_maxlifetime integer: specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up.
So, the session (idle or not) lifetime is decided with gc_maxlifetime, while the moment of the GC being started (as said in the docs: "potentially") is really decided with gc_probability and gc_divisor.
To resume, my late answer to the question would be - I would not under normal condition have GC running at each and every request (the 1/1 scenario you mentioned), because
that seems like a serious overkill. On some level, you would probably end up with thousands (if not worse) of IFs and only once going into its THEN
you would log out ANY user on your system after 60mins, not just the idle ones.
There are much better ways of doing this.
If this isn't for something particularly secure, you can set an expiration date/length for the session cookies on the client-side. A technically minded user could tweak the expiration in this case, so you wouldn't want to use this on a bank site.
If you need something more secure, just store an expiration time along with the other session data and check against it. If it's exceeded, destroy their session and force them to log back in.

session.gc_maxlifetime not expiring PHP Session

I have put:
php_value session.gc_maxlifetime 1
in my .htaccess file so my PHP Sessions should expire after 1 second but they are not.
I set a session and its still set after a few hours.
If i look at phpinfo() the session.gc_maxlifetime is set to 1 on the local value
any ideas why this is not working
As the php manual says:
session.gc_maxlifetime integer :
session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up.
Garbage collection may occur during session start (depending on
session.gc_probability and session.gc_divisor).
Note: If different scripts have different values of session.gc_maxlifetime but share the same place for storing the
session data then the script with the minimum value will be cleaning
the data. In this case, use this directive together with
session.save_path.
session.gc_probability integer:
session.gc_probability in conjunction with session.gc_divisor is used to manage probability that the gc (garbage collection) routine is
started. Defaults to 1. See session.gc_divisor for details.
session.gc_divisor integer
session.gc_divisor:
coupled with session.gc_probability defines the probability that the
gc (garbage collection) process is started on every session
initialization. The probability is calculated by using
gc_probability/gc_divisor, e.g. 1/100 means there is a 1% chance that
the GC process starts on each request. session.gc_divisor defaults to
100.
You also can refer this post.

retrieve php server session timeout

I want to retrieve the value of session.gc_maxlifetime from the PHP server settings ( the time after which the session expires after no activity ).
Very important : I do not want to change it, I only wish to retrieve its value ( maybe the value is different from server to server ) and I want to use a PHP script that I made to warn users properly, depending on the settings of those server.
Thank you.
That's where ini_get function comes in hand:
$maxlifetime = ini_get("session.gc_maxlifetime");
From manual we read:
session.gc_maxlifetime integer
session.gc_maxlifetime specifies the number of seconds after which data will be seen as 'garbage' and potentially cleaned up. Garbage collection may occur during session start (depending on session.gc_probability and session.gc_divisor).
session.gc_maxlifetime is not the time after which the session expires after no activity. gc here may be mean garbage collenction.
As the php manual says,
session.gc_maxlifetime specifies the number of seconds after which
data will be seen as 'garbage' and potentially cleaned up. Garbage
collection may occur during session start (depending on
session.gc_probability and session.gc_divisor).
Note: If different scripts have different values of
session.gc_maxlifetime but share the same place for storing the
session data then the script with the minimum value will be cleaning
the data. In this case, use this directive together with
session.save_path.
For more refer to this post.

session.gc_maxlifetime not working for me

i want to set session time out limit by 3 min ,
i have used this in the page
ini_set("session.gc_maxlifetime", "50"); not working
Solution for this
if (isset($_SESSION['LAST_ACTIVITY'])
&& (time() -
$_SESSION['LAST_ACTIVITY'] > 1800)) {
// last request was more than 30 minates ago
session_destroy(); // destroy session data in storage
session_unset(); // unset $_SESSION variable for the runtime }
$_SESSION['LAST_ACTIVITY'] = time();
// update last activity time stamp
Three variables are used to define the garbage collection behavior of PHP session variables:
session.gc_maxlifetime is the lifetime in seconds for the session
files (default value: 1440 = 24 minutes)
session.gc_probability is
the nominator for the probability to execute the garbage collector
(default = 1)
session.gc_divisor is the denominator for the
probability to execute the garbage collector (default = 100 or 1000)
The nominator and denominator are used together to determine the probability (nominator / denominator). So when session.gc_probability is 1 and session.gc_divisor 100 this is 1 / 100 = 1 %. So 1 % of every page visit (= every session_start call) the garbage collector is executed.
If you want to test how your session expires, you need to set session.gc_probability and session.gc_divisor to 1, so each page visit will cause the garbage collector to run. Furthermore you need to use two different browsers for the test.
The session of the first browser becomes cleaned when you visit your page with the second browser (and the session of the first browser is timed out). In my tests, when you use only one browser, the session becomes automatically extended although it is outdated.
The session will live as long as the file is left on the server's file system. They are cleaned out by a garbage collector. The garbage collector is run approximately every hundred page loads on the server (this is rather random, the "every hundred" page loads is just an average).
Also, the age of the session is inactive age, not total age. The timer will be reset for that session every time the user does a request.
The unit for the session.gc_maxlifetime value is seconds. So you would need to set it to 180 seconds to express 3 minutes.
But besides that, session.gc_maxlifetime is not reliable (see this post for an explanation). You should better implement that on your own to have your session expired after exactly 3 minutes.

Session timeouts in PHP: best practices

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');

Categories