Session cannot remain for a long time its automatically destroyed - php

I have an issue with session , my session is automatically destroyed after few minutes of inactivity ,i think its must be 24 minutes i.e. 1440 seconds.I want to session remain for a long time , i am using .user.ini file on the server and set session.gc_maxlifetime to 31557600 seconds and session.cookie_lifetime to 31557600 but nothing happened for me .Its still logout after 1440 seconds of inactivity .I have also attached session value of png image of phpinfo.
I hope your answer or any help will work for me.Thanks.

I'm not sure why your settings aren't working but I use the following on my scripts to overwrite the php.ini settings for session maxlifetime and session_save_path:
session_save_path('/pathto/writable/dir/on/your/account');
ini_set('session.gc_maxlifetime', 24*60*60); // 24 hours; change as necessary
session_start();
NOTE:
The session_save_path is important because the default path is /tmp and it may get deleted by the system administrator on a daily/week? basis.

In my experience, it's always been related to the php.ini file. In your case, the master and local values for session.gc_maxlifetime contradict. (gc stands for garbage collect) They don't have to agree with each other, since the local value is used for the running script. It just means there's two php.ini files on your system, located in different places, and the local php.ini file is overriding the master php.ini file settings. But, I'd be VERY suspicious of any files on your server which call session_start() which use the master php.ini file, or call ini_set(...) within the script itself. The way this works is that no matter what the value is set to, it only has meaning when it's time to do garbage collecting. And garbage collecting is done by session_start() but you can also trigger garbage collecting in other ways such as SessionHandler::gc or a cronjob as explained later in this post. When called, it checks the last modified time of the file on the server storing your session information. If the number of seconds that elapsed since then is greater than the current session.gc_maxlifetime value, it will destroy the session. Note this is the last modified time, not the last accessed time, so you'll want to change your session data frequently to prevent it from getting deleted if it's not changing. You should also be aware that there is a setting here, called session.lazy_write which, if enabled, and is enabled by default, WILL NOT update the last modified time of the session file in the event which the session data did not change. Thus you'll want to disable this if you want to minimize the chances of sessions being destroyed early for some unknown reason, or store a timestamp on the session so the data is always changing and you know when the session was last used, if old, you can manually call session_destroy(). To start another session, you can commit with session_write_close() then recall session_start(). Or, do all 3 at once with session_regenerate_id(true).
Nextly, if you initialize a session with session_start() with your intended settings, and continue to call session_start() with the intended settings with each request, awesome. But, once any file on your server calls session_start() with a different value for session.gc_maxlifetime, either from using the master php.ini value in your case, or the script calling ini_set(...) and ignoring the master value, it will check the file's last modified time against a different value and destroy your session despite your intended settings - is assuming it gets elected to be one of the 1 in 100 requests which have to garbage collect.
Another thing to be concerned with is session.cookie_lifetime. A value of 0 here turns the cookie into a browser session cookie. This means if the user closes their browser, then the session cookie will be deleted by the browser. Your master value is using 0. But your local value is using 31557600 (the average seconds in a year). So you should be fine here. But keep your eyes open if any scripts on your server override this value, use a value of 0, or use the master php.ini file.
You should also be aware of the default 1% garbage collecting CHANCE that a session will be destroyed as defined by session.gc_probability and session.gc_divisor which default to 1 and 100 respectively. Garbage collecting is done when start_session() is called, if, and only if, the request "randomly" gets picked to be the request to manage the Garbage Collecting. This means that even if the number of defined seconds for a session elapsed for it to expire, start_session() STILL won't garbage collect even for this expired session. Rather, most users will notice their sessions expire exactly to schedule due to the cookie the browser keeps track of having its timestamp expire. But the session isn't enforced until PHP garbage collects as per the garbage collection change when start_session() is called. If you want sessions to be wiped clean when they've expired, and start a new one, you should use session_regenerate_id(true). The true here means trash the $_SESSION data tied to the previous session and toss them a different session id as though their session expired.
You should also be aware that some systems, such as debian-based systems, have a cronjob which runs every 30 minutes to garbage collect based on the master php.ini configuration information.
See the comment here by Christopher Kramer: http://php.net/manual/en/session.configuration.php
I cannot verify if the above information about debian systems is true, but I've considered garbage collecting with a cronjob before to speed up users' requests so no one user gets stuck having to wait for their request to go through due to the maintenance which a cronjob could be handling.
In terms of solutions here:
One solution here is to adjust the master php.ini value, if you have access to it, then search your server for any PHP files which might be calling ini_set to see if there's any files conflicting with your settings to make sure they're not causing the unexpected behavior.
Another solution would be to limit such conflicts the script might be encountering by: (1.) renaming the session.name to something other than PHPSESSID. And/or (2.) changing the session.save_path path. Either of these by itself would suffice and avoid script conflicts.
A temporary fix might be to do something like change your session.gc_probability to 0 so the session garbage collecting NEVER happens. Or make it a much smaller chance by using something like session.gc_probability=1 and session.gc_divisor=100000. Then setup a cronjob to call SessionHandler::gc
See http://php.net/manual/en/session.configuration.php for more session config information.
Lastly I'd like to point you to this post which suggests good practices to prevent session hijacking, and for the most-part is the post I referenced when putting this post together: https://stackoverflow.com/a/1270960/466314
Note that it uses an approach to sessions which makes sure sessions expire on time, and not later (although browsers do a good job of this already with cookie garbage collecting). And it also makes changes to sessions, keeping track of the session last used time, so the session data is always changing to avoid the issue with session.lazy_write.
This concludes my suggestions. If you can narrow down the issue, try searching stackoverflow or asking a new question.

As stated here :
The best solution is to implement a session timeout of your own. Use a
simple time stamp that denotes the time of the last activity (i.e.
request) and update it with every request:
if (isset($_SESSION['LAST_ACTIVITY']) && (time() - $_SESSION['LAST_ACTIVITY'] > 1800)) {
// last request was more than 30 minutes ago
session_unset(); // unset $_SESSION variable for the run-time
session_destroy(); // destroy session data in storage
}
$_SESSION['LAST_ACTIVITY'] = time(); // update last activity time stamp
Updating the session data with every request also changes the session
file's modification date so that the session is not removed by the
garbage collector prematurely.

Related

PHP: Creating a "persistent" session for a webshop-like site

Hello everyone,
This is mostly a proof-reading question, if I may put it like that.
So, I need to create a persistent session for a webshop/e-commerce site. A session lasting over the specified time is not really an issue, but making it last for, say 24 hours since the last click, is important.
Why: To quickly check cart status, last visited pages, tax- and currency choices etc. without querying, let alone writing to the database or some other storage mechanism on each page request. The cart and browsing history are complicated enough to be stored in a session, Language, currency etc. could admittedly be cookies as well.
Most of our site is cached as html, and only a few elements like cart contents are strapped to the otherwise finished page. We have very good server response times, and I'd like to keep them that way and avoid anything too heavy especially for users who don't have anything in their cart.
I've gone through quite a few posts on StackOverflow and Google in general to get a basic idea of this. Most results were about being concerned and making sure the session would close in any case after a certain period of time. This case is the opposite.
So, PHP has a few session setting in the ini, of which three are the most important:
session.gc_maxlifetime: Determines the time after which a garbage collection cycle will remove the file. This is not an exact time, it
is a minimum time for the session to last since the last change of
the $_SESSION variable data. Default is 1440 seconds / 24 minutes.
session.cookie_lifetime: This is the lifetime for the PHPSESSID -cookie which enables PHP to fetch a corresponding session. This defaults to zero, which means the cookie is destroyed when the
browser closes. It could thus live for one millisecond or two years
if set to zero.
Setting this to an integer value will give the cookie an expiration
from the time it is first set. The lifetime will not be forwarded on subsequent page loads with session starts.
session.save_path: Tells PHP where to save the session files. This is also the directory which will get garbage collected for
expired sessions.
So here's an example "session header" I came up with. It should at least ensure session files are stored for at least $lt seconds from the first session start, and the session cookie $lt seconds from the last execution of this script. In the question -comment the session gets written to, which would in my thoughts cause the file time to get updated, and thus push session expiry to $lt since the last execution of the script.
<?php
/**
* Example "header" to start a session in a simple environment
*/
// Lifetime setting in seconds
$lt = 1440;
// Set maxlives to $lt
ini_set('session.gc_maxlifetime', $lt);
ini_set('session.cookie_lifetime', $lt);
// Save sessions in a different directory than other sessions. The gc
// will run on a probability base on each session start and clean the default
// directory. If our (longer) sessions are saved in a shared session dir
// for other PHP scripts which have a shorter expiry, our files will also be
// removed.
// If we run a single site, use php.ini to set the above max lives,
// or are the only ones using sessions, we can omit this directive.
ini_set('session.save_path', '/var/www/mysite/separate-session-dir');
// Start the session AFTER setting the parameters
session_start();
// Update the cookie expiration on a page load.
// This will simply overwrite the system-set session cookie.
setcookie(session_name(),session_id(),time()+$lt, '/');
// QUESTION: Would this forward the session FILE lifetime by writing to it.
$_SESSION['random-field'] = uniqid();
// Do what you really meant to do with your script.
So. Here it is. Does this work as a simple way to ensure sessions live for at least $lt seconds, or have I overlooked something?
I am currently running this on our server, without the ini_sets and save path as they are set in the php.ini instead. The cookie part seems easy enough to verify by closing the browser and returning to see if a cart is emptied or not, but the file -part is harder to verify and I'd like your input about this.
PS. Sorry about stuffing e-commerce/webshop tags, but I searched for hours for a post which would look at things from this perspective.

Understanding sessions in PHP

My questions:
session.gc_maxlifetime in php.ini: Does the session.gc_maxlifetime start from the session_start() point or the latest request to the server? (Assuming I have a few requests without a session_start() being called.)
What is the best practice to use the $_SESSION object so as to not waste precious RAM (automatically clear idle sessions in time)? Or is this something that happens automatically by the time mentioned in session.gc_maxlifetime?
How do I correctly check if a session has expired (as against a session which never got created)? Or are both the same? isset($_SESSION['any_variable']) === FALSE
Assuming I don't have control over php.ini, how do I increase session.gc_maxlifetime?
session_start(): If a session has "timed out", calling session_start will always start a session with the previous variables unavailable(a brand new session). Is that correct?
Good question! I would assume that the default filesystem session handler would go off last access but not all filesystems support an atime timestamp. I'll see what I can find out on that front.
Sessions are by default stored as files on disc. They only take memory when loaded. Unless you've built a custom session handler that stores sessions in a RAM disc or in a memcache server or similar, or unless you're storing a huge amount of state in the user's session I doubt memory use will be a major concern.
When session_start() is called the previous session data is loaded into PHP. If the session has expired then there will be no session data to load and a new empty session will be created. So yeah, if you check for the existence of a variable in $_SESSION that you're expecting to always be there then you can use that to determine if the user's session has expired (but only after session_start() was called).
Simply set gc_max_lifetime to how long you want sessions to last in seconds. 600 is 10 minutes, 86400 is one day, etc.
Yes (with some caveats, see below).
There are a few things you need to be aware of with sessions though. First is that there's two components to a session: A server side state record that holds all the data stored in the session, and a client side token that PHP uses to associate a particular user with a particular state record. Normally the client side token is a cookie. Cookies have their own expiration date, so it's possible that the session can expire before the session state is due to do so. In that case the user will stop sending the token and the session state is effectively lost. If you're adjusting how long a session lasts you need to set both the server side state expiration time and the client side cookie expiration time.
As for stale state, the session garbage collection system doesn't always run every time session_start() is called. If it was the overhead would be crippling to a big PHP site with a lot of sessions. There are configuration options that specify the probability that the GC will run on any given invocation of session_start (I believes it defaults to 1%). If it doesn't run then a stale session record may still be treated as valid and used to populate $_SESSION. It probably won't have a serious effect on your system but it's something you need to bear in mind.

I'm trying to increase session timeout time

I am trying to increase the SESSION time so that the users do not time out for 12 hours. This is a private site used only by employees and the timeout is annoying and it causes partially filled out data to be lost. According to what I read the following code should work:
ini_set('session.gc_maxlifetime',12*60*60);
ini_set('session.gc_probability',1);
ini_set('session.gc_divisor',1);
session_start();
but it has no effect. Any thoughts?
thanks
ini_set('session.gc_probability',1);
ini_set('session.gc_divisor',1);
These two are forcing PHP to run the session cleanup script for EVERY hit on your site. PHP's formula to run the gc is:
if (random() < (gc_probability / gc_divisor)) then
run_session_garbage_collector()
}
Right now you've got 1/1, so 100% chance of the garbage collector being run. While extending the timeout period is good, you also want to REDUCE the chance the collector runs at all. Otherwise you're forcing PHP to do a full scan of ALL session files and parse EACH one, for EVERY hit on your site, to find the odd one or two that might have expired.
Try setting the gc_probability to 0 to completely disable the garbage collector.
As well, be aware that changing the settings, as you are, within a script with ini_set() doesn't change the timeouts/defaults that OTHER scripts use. This script might have a longer timeout and changed probability, but if other scripts hav ethe default timeout (10 minutes or something), then they'll happily nuke any "stale" sessions.
The proper place to set session timeout/cleanup settings is at the php.ini level, so that it applies to all scripts on the site, not just this single script of yours.
You could try setting the session.gc_maxlifetime = 12*60*60 in your php.ini file.
Otherwise when your script ends the session.gc_maxlifetime variable will be reset each time.
from php.net/ini_set :
string ini_set ( string $varname , string $newvalue )
Sets the value of the given configuration option. The configuration option will keep this new value during the script's execution, and will be restored at the script's ending.
The session cookie might be expiring as well: session.cookie-lifetime
I'm not sure if by "private site" you mean its alone on a dedicated server, but if not:
If your session temp files are being stored in the same directory as other sites' tmp files, its possible that a lower session lifetime on another website is triggering garbage collection, which could delete your "private site's" session. Depends on server setup. Personally I've got a tmp folder for each client to avoid things like that.
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.
So your doing 1/1 - I'm not sure how that will actually function, but it could be odd behavior.
Hope this will help you. just copy and paste the bellow code in web.config file
<sessionState mode="InProc" stateNetworkTimeout="10" sqlCommandTimeout="30" cookieName="ASP.NET_SessionId" timeout="53200" regenerateExpiredSessionId="false">
<providers><clear/></providers>
</sessionState>

How does a server judge a session to be expired and how can the expiry time be changed?

I understand that a session cookie can be given a lifetime (session.cookie_lifetime) and that after that lifetime the cookie expires regardless of whether a user interacts with the site.
I would therefore assume to set this to 0 to indicate they should stay live until the browser closes.
I also think I understand that the garbage collection lifetime (session.gc_maxlifetime) can be set for a cookie and that as long as a user does not exceed this time between their clicks then the cookie will remain active.
To test this out I've been trying to get a 10 second session timeout.
I tried:
ini_set('session.gc_maxlifetime',10);
but the session doesn't timeout after 1 minute at least.
Is this because I am only saying to the garbage collector that the session has a life of 10 seconds but I'm not actually triggering the garbage collector?
How do you set the garbage collector going or does it just run every time a session is requested?
First of all, don't confuse cookie settings (which are client-side) and garbage collection (which is server-side). Cookie settings only affect the expiration of the session_id. Session data may still exist on the server even if the browser has removed the cookie and, on the contrary, the server can remove the data while the session_id is still remembered by the browser.
The cookie can be set to expire when you close the browser or in a specific date and time (I believe the default option is the first one, but I'd have to check it). In both cases, if the user interacts with the site the cookie will remain valid since it's renewed on each response.
Session data is removed when the garbage collection is launched but you must take into account that:
The garbage collection is started randomly, triggered by a page request.
It removes session data not modified in more that gc_maxlifetime seconds.
By default, session data is stored in files and PHP doesn't track what site owns what files. That means that storing sessions in the default shared location makes you lose control on session expiration: the site that's configured to keep session data for the shortest time is likely to remove data from other sites with longer time.
To sum up, if you want full control on your data lifetime you need to store session data in a private directory, e.g.:
session_save_path('/home/foo/sessions');
ini_set('session.gc_maxlifetime', 3*60*60); // 3 hours
ini_set('session.use_only_cookies', TRUE);
session_start();
The server has a default timeout set in it's INI files, if not overridden from within a script. In apache it is set from within PHP.ini i believe. You also need to enable the garbage collection function, which I believe is also set in php.ini.

everlasting sessions in PHP

Is it possible to configure PHP sessions to never expire? I currently have the default 24 minutes set in php.ini - I could whack this up to a couple of weeks or something like that but I was wondering if I can set them to infinite lifetime?
I want to achieve a similar effect to Stackoverflow's: I never have to log in here. Is this achieved on SO with a never-expiring session or some other means?
Also, as a secondary question: How do the expired session files get cleaned up? If someone creates a session and never returns, which process is cleaning up their expired file?
Normally, what appears to be an everlasting session is two things: a session, which expires pretty soon, and a very long-life cookie containing an auto-login token.
There's a great series of responses on sessions and logging-in contained in this StackOverflow question: The Definitive Guide To Website Authentication
Regarding your question about when sessions are cleaned up, there are several php.ini settings for controlling when the garbage collection for sessions is triggered.
Since PHP both allows and encourages you to create your own session data storage handlers, there is no single correct answer to this question.
Answer to secondary question
Session file cleanup is controlled by the following 3 php.ini settings:
session.gc_probability (default value 1)
session.gc_divisor (default value 100)
session.gc_maxlifetime (specified the age after which the session is considered as garbage)
First 2 settings specify the probability of the garbage collection process being started at session start (before or at the very beginning of your script execution, depending on how you have set things up)
In default configuration there is a 1% probability then that this happens. If it does, then files that are older than maxlifetime are cleaned.
As for your first question - why not write a custom session handler, that stores sessions inside the database (if you have one). That way you can see and control the sessions right from inside the database. Handy :)

Categories