1

Preface: this is a "development" from an earlier question of mine, whose answers didn't solve my problem in the end. But through trying all the suggestions and also trying other stuff, I discovered that the real problem is something else, so I rephrase my question here

I have a login page/system which has worked correctly for years, leaving the user logged in until he/she either closes the browser window or logs out manually. But lately after only a few minutes of inactivity the session cookie/s seemed to expire, causing the user to be logged out automatically.

This happens on different browsers and different operating systems, the PHP version is 5.6.29, which has been changed recently (before it was 5.5 and even 5.3).

I create and refresh the session on every page with session_start(). The login script first checks user name and PW and also gets some other user data from the database. These other data and the successful login state are saved in session variables like

$_SESSION['username'] = $name;
$_SESSION['usertype'] = $type;
$_SESSION['login'] = "ok";

On the other pages I check the login state like this:

session_start();
if(($_SESSION['login'] != "ok") OR ($_SESSION['usertype'] != "xxx")) {
 header("Location: ../login.php"); /* redirects to login page if conditions are not true */
 exit;
 }

The login works, and logged-in users can proceed to other pages for some time, but after some time (varying strongly), he/she seems to be logged out (i.e. redirected to the login page when trying to open another page).

Then I noticed (in the developer tools) that the session ID cookie kept the same value after the session seemed to have expired (which I had thought, since the session variables were gone). But the session didn't expire, only the session variables had disappeared. In my tests I tried echoing some of those variables on some pages, and rather by accident I discovered that after they already had disappeared (no echo output) they reappeared after a few minutes when I reloaded the page or changed to another page.

Now that's where I am stuck at the moment: How can this happen, and especially: What can I do to prevent those variables from playing hide-and-seek?

(BTW, I don't have access to the server settings - this is on a shared webspace...)

Community
  • 1
  • 1
Johannes
  • 64,305
  • 18
  • 73
  • 130
  • If the php versions were changed, check to see if the session cookie life settings were also changed/modified. This is all I can get from this. What does `phpinfo()` show? – Funk Forty Niner Jan 05 '17 at 17:07
  • Check php.ini settings like @Fred-ii- has said, but also, and I know it sounds silly, check your code for `$_SESSION[.....] = ....` when you really meant `$_SESSION[.....] == ....` A very commonly missed typo. – Chris Jan 05 '17 at 17:09
  • Is this a single server, or multiple servers behind a load balancer? ;) – Crouching Kitten Jan 05 '17 at 17:09
  • `session.cookie_lifetime` is set to 0, `session.gc_maxlifetime` to 1440. Also, they wouldn't reappear if it really expired, and the session ID wouldn't remain the same, would it? – Johannes Jan 05 '17 at 17:11
  • @CrouchingKitten it's a shared webspace – Johannes Jan 05 '17 at 17:13
  • not sure it would help or not but pls go through it : http://stackoverflow.com/questions/11210860/php-sessions-not-always-working – prakash tank Jan 05 '17 at 17:15
  • The session cookie holds nothing but an identifier. The actually session data is stored server-side. If the server-side session data is destroyed then the session cookie will no longer point to valid session data. – GordonM Jan 05 '17 at 17:15
  • @Chris with `$_SESSION[.....] = "..." I defined the variables, assigning them values I get from a database. Later on I compare these with "==" – Johannes Jan 05 '17 at 17:16
  • Well, this could just be a logic thing. `if(($_SESSION['login'] != "ok") OR ($_SESSION['usertype'] != "xxx"))` - or an operator. did you try `||` instead of `OR` and checking if both are set/not empty? Rather than using `OR` you could try `AND` - `&&`. – Funk Forty Niner Jan 05 '17 at 17:16
  • @Fred-ii- Actually, that `OR` could also be `AND` - it wouldn't make a difference (I hadn't noticed that until now). But when this problem appears, actually *all* session variables disappear (I echoed them on the same page to test this). But as I wrote - sometimes they reappear after sometime when I just reload the page. – Johannes Jan 05 '17 at 17:22
  • @GordonM but the strange thing is that they reappear after some time! – Johannes Jan 05 '17 at 17:24
  • 1
    Hmm none of the previous guesses would explain why can the session values recover after a while. Do you use the default session storage? (which is the filesystem) If the provider has an architecture with multiple machines behind a load balancer, then you would need to store the session in a DB table. (Because the machines must use the same db) – Crouching Kitten Jan 05 '17 at 17:24
  • This could also be db-related as you stated in comments that one is being used. If something is being written to a column that shouldn't be written to, or was not written to due to an unexpected reason/error, or wrote the wrong value and relying on a value of sorts, then this could also be a possible reason. Other than that, I stand "baffled" myself. Maybe a time/date (my)sql / php / server location difference? – Funk Forty Niner Jan 05 '17 at 17:25
  • 1
    What session storage mechanism are you using? If it's the default one (to a temp file) then some maintenance/backup scripts running on the server might be deleting session data as junk while another is restoring the data from backup. If it's using a database or memcache then maybe the servers for those are becoming temporarily unavailable? Just speculating here – GordonM Jan 05 '17 at 17:26
  • session storage is left at default, which is `/tmp` – Johannes Jan 05 '17 at 17:27
  • @Fred-ii- No, maybe I expressed that poorly: I only *get* values from a database (which I compare to the login form data), I don't *write* anything session-related into it – Johannes Jan 05 '17 at 17:29
  • @Johannes Ok, I understand. Well... my last ditch effort. If this is related to your tmp folder; could it be that it gets filled up and the server takes a few minutes to empty it out, and during that time since it's full, it can't write to it? Sorry if I'm picking at straws here, but that's the scope of what I know. – Funk Forty Niner Jan 05 '17 at 17:31
  • 1
    @Fred-ii- Thanks for trying to help! But picking up your thought: The data (session variables) are written in there during login - after that they are not altered, only read out. And if `tpm` would be emptied at any point, they would be lost and couldn't reappear after a few minutes.... – Johannes Jan 05 '17 at 17:34

2 Answers2

1

This is not a solution, just a test for the case I wrote about in the comments. Could you try this?

<?php

$number = (int)$_GET["number"];
$temp_dir = "/tmp/lbtest123";

if (!is_dir($temp_dir)) {
    if (!mkdir($temp_dir, 0777, true)) {
        die("Can't create directory: $temp_dir");
    }
}

file_put_contents($temp_dir."/".$number.".txt", "");

echo "<pre>\n";
print_r(glob($temp_dir."/*.txt"));
echo "</pre>";

Copy this to your server. It creates files in the /tmp/lbtest123 folder, using the number passed as a parameter. Then lists the files already created.

Call it with increasing numbers, for the same amount of time you expect the "logout" to happen. Example:

Example result:

Array
(
    [0] => /tmp/lbtest123/1.txt
    [1] => /tmp/lbtest123/2.txt
    [2] => /tmp/lbtest123/3.txt
    [3] => /tmp/lbtest123/4.txt
)

I expect it to show something like these after a while:

Array
(
    [2] => /tmp/lbtest123/4.txt
    [3] => /tmp/lbtest123/5.txt
)

Array
(
    [0] => /tmp/lbtest123/1.txt
    [1] => /tmp/lbtest123/2.txt
    [2] => /tmp/lbtest123/3.txt
    [3] => /tmp/lbtest123/6.txt
)
Crouching Kitten
  • 1,135
  • 12
  • 23
  • You may be right, I suppose, but that amount of time is pretty unpredictable. Until now it ranged from 3 minutes to 6 hours... The reason why I think this could be true is a non-reproducable observation I made - I had logged in as another user after the first connection failed, then got the second user echoed for a while (an hour?), and suddenly got the data of the first one echoed again... But anyway - what can I do if it is like that? – Johannes Jan 06 '17 at 00:23
  • @Johannes: if that's the case, then you could contact the provider, or you could store the session data in a database table: (sess_id, data, last_access_time), etc. And also double check the possibility that another application on the same host is tempering with the same session. To rule this out just change the cookie name to something else. – Crouching Kitten Jan 06 '17 at 08:49
1

For anyone who is interested:

Obviously @Crouching Kitten was right - the provider has an architecture with multiple machines behind a load balancer or something similar, and there is nothing I can do about this.

So I took his advice and now save everything that had been session varibles before (together with the session id) in a database which I access at the beginning of each page of that website. I also save a timestamp in there, which gets updated with every new query containing the same session ID, so I could set up a cronjob that erases outdated data (older than 90 minutes - but that interval can be anything) every half hour.

Johannes
  • 64,305
  • 18
  • 73
  • 130
  • I strongly suggest memcached based session handler. It's faster and everything is in-memory, has very little footprint, has a TTL, has no file locking (HHVM has no locking on session files, too, similiar behaviour) and you can have all the session data available on all the webservers. – Daniel W. Jan 10 '17 at 16:53
  • Unfortuately, I have no possibility to change server settings (except ini_set() and related stuff) - I am a mere client of a rather unflexible provider. – Johannes Jan 10 '17 at 16:58
  • This would be inacceptable for me. When you pay for it but it only works in special cases (when a user hits the same backend machine with every request), this is a good reason to immediately discard the contract or even ask to get your money back. – Daniel W. Jan 10 '17 at 17:00
  • yes, true. But more precisely I am not even the client, but the web worker of the client, and also that client isn't too flexible... – Johannes Jan 10 '17 at 17:03