2

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.enter image description here

Amy
  • 161
  • 1
  • 10
  • Have you set `session.gc_maxlifetime` and `session.cookie_lifetime` _before_ start the session with `session_start`? – Federkun Oct 12 '15 at 15:35
  • @nope i wrote only session_start(); – Amy Oct 12 '15 at 16:43
  • if you do `echo ini_get('session.cookie_lifetime');` before `session_start`, whay do you get? – Federkun Oct 12 '15 at 16:44
  • wait a min i m checking – Amy Oct 12 '15 at 16:44
  • its right said i.e. 31557600 – Amy Oct 12 '15 at 16:46
  • can you check if your cookies are set with the right lifetime? do you call `session_unset` / `session_destroy` somewhere in your application? have you saw the answer of @Pedro Lobito about the `session_save_path`? – Federkun Oct 12 '15 at 16:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/92077/discussion-between-amy-and-federico). – Amy Oct 12 '15 at 19:00

3 Answers3

2

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.

Pedro Lobito
  • 94,083
  • 31
  • 258
  • 268
2

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.

Community
  • 1
  • 1
Ultimater
  • 4,647
  • 2
  • 29
  • 43
  • 1
    **TL;DR** something like `ini_set('session.save_path',realpath(dirname(dirname($_SERVER['DOCUMENT_ROOT'])) . '/session'));` (calling dirname on a directory tells you the directory of the directory) would be an ok solution to avoid script conflicts. Just keep in mind all the concerns mentioned in the post and make sure to store a timestamp in the session like the post here suggests: http://stackoverflow.com/questions/520237/how-do-i-expire-a-php-session-after-30-minutes/1270960#1270960 – Ultimater Oct 13 '15 at 06:09
1

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.

Community
  • 1
  • 1
LeRoy
  • 44
  • 5