PHP sessions expiring

I am having problems with a PHP site where I start work when users log out after a few minutes (the exact time changes, but often enough to be a problem), regardless of whether they were active using the site or not.

The difficulty is that I cannot reproduce this problem, if I log in, when the same users use the same browser, I do not log out, which suggests that this is not the case when the site is completely broken. Unfortunately, I do not have access to user machines to run any traffic tracking software.

What I already checked is:

  • Ask users to try different browsers. This does not seem to solve the problem and is not a long-term solution, since I cannot dictate which browser clients will use.
  • Server time is correct and corresponds to user machines.
  • The Apache user works the same way as he has write permission to the session folder, and I can see the created session files and the time of their modification.
  • No output buffering functions are used.
  • The problem occurs on different pages that seem to have nothing in common (i.e. not all of them use AJAX or update the database or for some other reason).
  • Users only get access to their account from one computer, i.e. they don’t work on their laptop, switch to the desktop, and then wonder why they went to their laptop (we do not allow multiple simultaneous logins for the same user).

Session parameters in PHP are Debian defaults and have not been changed in the .htaccess file or elsewhere. The main ones are:

session.cookie_lifetime 0 session.gc_divisor 100 session.gc_maxlifetime 1440 session.gc_probability 0 session.save_handler files session.save_path /var/lib/php5 session.use_cookies On 

Debian deletes sessions via the cron job instead of using the PHP garbage collector, so gc_probability is set to 0. The PHP version we are running is: PHP 5.2.6-1 + lenny13 with Suhosin-Patch 0.9.6.2 (cli) (latest version in Lenny, we'll get to Squeeze soon, but I don't think this is causing the problem.)

We use Zend_Session to manage sessions, and an instance of Zend_Session_Namespace is created once on each page, thus automatically calling session_start (). Sessions are cleared by calling Zend_Session :: destroy () on the exit page, so the only ways to exit the system are:

  • If they explicitly click on the exit link (we register when this happens, and it seems that the page’s prefetching and thus the user’s registration are not visible).
  • If they leave a session inactive for more than 24 minutes, Debian will probably delete its session at that point (there will be a cron job that every half hour will delete all sessions that have been unmodified for more than 24 minutes).
  • If they close the browser, because their session cookie with the expiration of time 0 will be deleted.

Checks if a user is registered:

  • They have a valid session (it is checked whether we can access $ zsession-> user_id).
  • There is a row in the session table that has the corresponding user ID and session ID, and this was the last update less than an hour ago. We delete this line when we log out, so even if the session still exists on disk, no one can access this account without logging in.

Can anyone suggest other things that I can try?

Edit: some additional things I tried based on the comments on the left:

  • Setting session.cookie_domain: This seems like a very strange behavior in PHP. If I do not set this variable and leave it as the default value '' (empty line), then a request to www.domain.com will trigger the cookie www.domain.com. However, if I set cookie_domain to "www.domain.com", the domain for the cookie will be ".www.domain.com" (note the leading dot, which means valid for everything below www.domain.com, for example, subsite .www.domain.com).
  • Setting session.cookie_lifetime: PHP does not seem to update the expiration time for each request, so if I set cookie_lifetime to 3600, the cookie will expire one hour after the user's first visit to the site, even if they log in and use it constantly.

Edit 2: based on other things, people asked:

  • The site is located in a data center in a separate VLAN. No one accesses a site on the same network as the site.
  • IP authentication is not used, as well as the client IP address used in any part of the session (for example, we do not attach the session to the IP address and block the user if their next request comes from another IP).
+7
source share
8 answers

In the end, the answer was simply to conduct sessions and write your own very simple cookie, which differs from sessions in the following ways:

  • Saves the hash (bit as a session identifier) ​​in the database, not in files.
  • Sets the cookie to expire after 3600 seconds (updated on every page) instead of 0 seconds (the latter seemed to cause problems for IE users, although I could never reproduce it).
  • Only sends the cookie header when the user logs in or logs in.

This is not an ideal situation, as some reinvent the wheel, but my little solution seems to work where there were no PHP sessions, and a working site is the most important thing.

+1
source

Debian Deletes Sessions Through Cron Job Instead of Using PHP Garbage Collector

This is very strange - and what is the code running in the cron job?

We delete this line when we log out

I suggest you keep this, say, 2 days after the session has expired / deleted (but mark it as dead in the place where you are currently deleting it). Also start logging session IDs in web server logs.

+3
source

I think you think you change the meaning

 session.gc_maxlifetime 

I also ran into the same problem. I spent a lot of time on this, then I ask my web service provider, and when he got permission, he changed this valley. Now it works great.

+1
source

Are there other php applications on the same system (e.g. for different vhosts)? Do they also save sessions in / var / lib / php 5?

If so, and one of these applications has a low garbage collection threshold, they will destroy your application's session files.

I am developing ZF, and if I use file system based sessions, I use them in the / data / session application instead of the system default.

+1
source

- your site in different domains? e.g. domain.com, www.domain.com, subdomain.domain.com? if some pages are redirected to another domain (www is considered a subdomain, which is different from the fact that sessions will not work when the address changes

EDIT: You have to reproduce the problem. Ask your customers which browser they use, what action they perform until they log out, do they look at the same ip for the site as you? (that is, you are both in external networks, and in the same network with the site)

When you manage to find the problem, check the request / response headers when the session is running, as well as when it does not work, and then compare.

0
source

your session.gc_maxlifetime is set to 1440 ms, which is only 1.44 seconds. shouldn't be 1440000 ms = 24 minutes?

0
source

You can try setting session.use_only_cookies to 1 and session.cookie_lifetime to 1440 seconds.

0
source

In the end, I decided to send a Set-Cookie header for each page request, similar to what FlyBy suggested in one of the comments. Corresponding code / logic now (if session_start () is already called):

 $this->session_name = session_name(); $update_cookie = isset($_COOKIE[$this->session_name]); // Check if cookie already set, as PHP will send the first Set-Cookie when the session is started $this->logged_in = $this->checkSession(); // Function which checks whether a valid (ie not timed-out) session row exists in the DB if ($this->logged_in) { $this->updateSession(); // Update the session row to the current time if ($update_cookie) { // Update the cookie expiry only if it existed before the login check setcookie($this->session_name, $_COOKIE[$this->session_name], $this->time + 3600, '/'); } } 

I'm not sure why this worked, but I had no further complaints, and the number of logins dropped sharply (there are no more multiple logins for the same user in the logs for several minutes from each other).

However, I probably at some point rewrote the code to just use the database row and cookie on the client, because the session functionality in PHP has so many variables that it is extremely difficult to determine what causes the problem, and processing Session cookies are slightly different from how regular cookies are processed. In particular, you should be careful with the setcookie function, because the default path for the session cookie launched by PHP is '/', but the default path for setcookie is the current directory path and they will not necessarily be the same.

0
source

All Articles