11

I have a problem with a website where PHP does not save session variables for specific users with Internet Explorer. But for some other users with Internet Explorer there is no problem at all, and users with other browsers also do not have any problems.

I created the following three small scripts to make sure no other code in the website was involved:

test.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test.php");
logMsg($content);

$_SESSION['test'] = array('test' => 'lalala');
$_SESSION['count'] = 1;
?>
<a href="test2.php">Next</a>

test2.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test2.php");
logMsg($content);

$_SESSION['count']++;
?>
<a href="test3.php">Next</a>

test3.php:

<?php
session_start();

function logMsg($text) {
    $filename = dirname(__FILE__) . "/test.log";
    $fh = fopen($filename, "a") or die("Could not open log file.");
    fwrite($fh, date("d-m-Y, H:i")." - $text\n") or die("Could not write file!");
    fclose($fh);
}

ob_start();
var_dump(session_id(), $_SESSION, $_SERVER, $_REQUEST);
$content = ob_get_clean();

logMsg("test3.php");
logMsg($content);

The expected output for the var_dump($_SESSION) would be something like:

array(0) {
}

array(2) {
    ["test"] => array(1) {
        ["test"] => string(6) "lalala"
    },
    ["count"] => int(1)
}

array(2) {
    ["test"] => array(1) {
        ["test"] => string(6) "lalala"
    },
    ["count"] => int(2)
}

However, the output for the users with the problem is the following:

array(0) {
}

array(0) {
}

array(1) {
    ["count"] => int(1)
}

This means that the session variables are not stored for these users. However, the session ID for the users with problems is the same for all 3 test pages.

Does somebody have any idea what this could be? As far as I know the problematic code has worked for several years and the problems started showing in the last month or so.

Edit

Answers to questions in the comments:

  • I cannot replicate the problem on a local machine.
  • I have reports of problems from users with IE7 and IE9. But I cannot say for certain that there are no problems with the other versions, because it could be that these are simply not reported yet.
  • The browser of a user with the problem does not have cookies disabled, the PHPSESSID cookie is sent to the server.
  • There are no - or _ in the machine name (https://stackoverflow.com/a/306601/534109).
  • Regenerating the session id with session_regenerate_id() has no influence on the result for the users with the problem.
  • Timezone and time settings for a user with the problem are the same as on the server.

Edit 2

As stated by @nl-x in a comment the data gets stored in the second request. So I adapted the test scenario and added another step to see if the sessions works in subsequent requests. And this is the case. Session data set in step2.php and step3.php are saved between requests.

So now the question is why does session data for the first request get lost and not for subsequent requests?

Community
  • 1
  • 1
Jan-Henk
  • 4,864
  • 1
  • 24
  • 38
  • 1
    @GungFoo How so? IE9+ has very good standards support. – Tieson T. May 29 '13 at 08:21
  • 1
    @HamZaDzCyberDeV About 30% of the world, it seems: http://www.sitepoint.com/browser-trends-march-2013/ – Tieson T. May 29 '13 at 08:22
  • 3
    Do the specific users have cookies disabled? – Phil Cross May 29 '13 at 08:22
  • Ah by the way, have you implemented "cookie wetgeving" ? Maybe some users did not accept your cookies ? – HamZa May 29 '13 at 08:23
  • @TiesonT. Sadly enough ... :( – HamZa May 29 '13 at 08:23
  • Nope they don't have cookies disabled. From the var_dump($_REQUEST) I can also see that the PHPSESSID data is sent to the server for these users. – Jan-Henk May 29 '13 at 08:24
  • There is no cookie wetgeving code in the small test scripts I provided @HamZaDzCyberDeV. – Jan-Henk May 29 '13 at 08:25
  • Ignoring the IE trolls for just a moment and getting back to the actual question, please could you tell us which IE version(s) you're having problems with. – Spudley May 29 '13 at 08:33
  • Not trolling at all, I tested it on IE8 and it works as expected. If we can't reproduce the "error" it will be difficult to solve your problem. – HamZa May 29 '13 at 08:35
  • I have reports of problems from users with IE7 and IE9. But I cannot say for certain that there are no problems with the other versions, because it could be that these are simply not reported yet. And I cannot replicate the problem on a local machine. – Jan-Henk May 29 '13 at 08:36
  • @Jan-Henk A browser won't just block a cookie from itself, it has to be configured to do this. If you can't even reproduce the error it would be almost impossible for us. What I suggest is to log the users and check if [they are using cookies](http://stackoverflow.com/q/9448424). If you could ask those who reported the problem to cooperate that would be better. – HamZa May 29 '13 at 08:42
  • 1
    @HamZaDzCyberDeV I have at least one user with the problem that will cooperate with me. He does not have cookies disabled, no antivirus software that interferes and the problem does exist for him in the small test scripts I provided. – Jan-Henk May 29 '13 at 08:44
  • Strange ... I'll be watching from the sideline for now ... – HamZa May 29 '13 at 08:47
  • Why do you regenerate the id ? (second code line) – nl-x May 29 '13 at 08:47
  • 2
    @nl-x preventing session hijacking ? – HamZa May 29 '13 at 08:48
  • @nl-x I read somewhere that regenerating the session ID solved a similar problem, so I tried that. But whether the statement is in the code or not has no influence on the result for the users with a problem. But I will edit it out of the example code, the smaller the testcase the better. – Jan-Henk May 29 '13 at 08:50
  • You say `This means that the session variables are not stored for these users.` I disagree: the session is not stored on the first request, but seems to get stored on the second request. As on the third request, the count is remembered... – nl-x May 29 '13 at 08:53
  • 3
    This seems to be a caching issue on the computers where people complained that sessions aren't working. Sadly, it's out of your control to fix that and if you can't replicate the problem, the best you can do is to inspect their IE configuration and whether they're behind a proxy. Without that information, you can't create a fix because everything works fine on PHP side. – N.B. May 29 '13 at 08:56
  • @nl-x You are right that the data gets stored on the second request. I will add another step in the test scenario to see if data in the third request will be stored or not. I'll get back on this when I have an answer from the user. – Jan-Henk May 29 '13 at 08:59
  • Misconception about cookies `Cookies will not become visible until the next loading of a page that the cookie should be visible for. To test if a cookie was successfully set, check for the cookie on a next loading page before the cookie expires. Expire time is set via the expire parameter. A nice way to debug the existence of cookies is by simply calling print_r($_COOKIE);` [source](http://uk.php.net/manual/en/function.setcookie.php). So the behaviour of the first test is expected. – HamZa May 29 '13 at 09:00
  • @HamZaDzCyberDeV OP also says he expects it that way. His *expected output* starts with `array(0) { }` – nl-x May 29 '13 at 09:09
  • @nl-x I edited the OP, because as you stated, only the session data from the first request gets lost, not the data for subsequent requests. – Jan-Henk May 29 '13 at 09:31

4 Answers4

5

I figured out that the users that were having the problems all had Chrome Frame installed. I verified this by installing Chrome Frame on a local machine, and in this case I was able to replicate the problems.

The problems were caused by the fact that our server has Suhosin installed. The following Suhosin settings were enabled:

suhosin.session.cryptua
suhosin.cookie.cryptua

This means that the User Agent string is also a part of the identification of a user's session. Normally this is not a problem, but for users with the Chrome frame installed the User Agent string differs between the first request and the subsequent requests. After disabling these Suhosin settings there were no more problems.

Jan-Henk
  • 4,864
  • 1
  • 24
  • 38
  • Awesome. That is definitely not something I considered, but it makes sense (good to know, as well). Good work. – Tieson T. May 30 '13 at 19:43
2

I will posit this, in lieu of waiting for someone with specific knowledge of PHP's session mechanism:

I work mostly with ASP.NET, and the Session object uses a cookie to persist data across requests. If PHP works the same way, the most obvious conclusion is that the users with session issues either have cookies disabled or are using software that only allows whitelisted domains to set cookies. I will see if I can find any facts to back this theory up...

From the PHP manual (http://www.php.net/manual/en/intro.session.php):

This is either stored in a cookie on the user side or is propagated in the URL.

Tieson T.
  • 20,774
  • 6
  • 77
  • 92
  • I know for sure for at least one user with the problem that he has cookies enabled. – Jan-Henk May 29 '13 at 08:33
  • @TiesonT. Yes, PHP's cookies work much the way you've described. – Spudley May 29 '13 at 08:35
  • @Jan-Henk Figures. That would have been far too easy to be the actual problem, no? – Tieson T. May 29 '13 at 08:37
  • @Jan-Henk Does this answer to a similar question raise any concerns?: http://stackoverflow.com/a/306601/534109 – Tieson T. May 29 '13 at 08:43
  • @TiesonT. I already found that bit of information myself, but there are no - or _ in the machine name. But thanks anyway. – Jan-Henk May 29 '13 at 08:46
  • @Jan-Henk One last thought: is there a great enough difference in timezones for the user(s) in question to have an "expired" session? I've read an article or two that says IE has been known to incorrectly calculate timespans from local time rather than matching the server's timezone first... – Tieson T. May 29 '13 at 08:54
  • @TiesonT. I'll ask the user about his timezone. – Jan-Henk May 29 '13 at 09:00
  • @TiesonT. Same idea popped into my head. But isn't the session cookie meant to be a session-cookie :) ? (Meaning the cookie has no expiration, but is thrown away when the browser leaves.) – nl-x May 29 '13 at 09:03
  • @nl-x To be honest, my PHP days are behind me, but doesn't look like it has to be: http://www.php.net/manual/en/session.configuration.php#ini.session.cookie-lifetime – Tieson T. May 29 '13 at 09:08
  • From a `phpinfo()` call I get the value 0 for `session.cookie_lifetime`. – Jan-Henk May 29 '13 at 09:11
  • @TiesonT. His timezone settings and time are the same as the server. – Jan-Henk May 29 '13 at 09:22
  • After capturing network data from users with problems I figured out that users with problems had Chrome Frame installed. With this extra bit of information I found out what the problem was, I have explained this in an answer of my own. But thanks for your help. – Jan-Henk May 30 '13 at 19:00
1

I can't exactly tell you why on/after the first request, the cookie seems to get lost. (That is what I guess is going on.) And why on/after the second request is does NOT get lost.

Perhaps indeed a caching issue. Check the Developer tools, and look at what exactly is going on in the network tab. Is the first request coming in with a 200 - OK, and does the response contain a cookie header? Or is it indeed cached, as one of the comments suggested?

But in the end you should actually implement correct session id passing (read it). This is meant for people who dont want or can't handle cookies.

Basicly it means changing:

<a href="test3.php">Next</a>

into:

<a href="test3.php?<?php echo htmlspecialchars(SID); ?>">Next</a>

or:

enabling --enable-trans-sid

Now when PHP notices sessions are not passed by cookies, it will give them along in a less secure way, in the URL. Especially in this case you would need session_regenerate_id().

edit: Ow yeah, I wanted to mention it earlier, but then thought it couldn't be it. But on second thought I will still mention it! :

Cookies are domain specific by default. If the user goes to http://yourdomain.com (without www.) , and the second request goes to http://www.yourdomain.com , the cookie will not survive the domain change! Thus affecting your session.

To fix this, either set the session cookie domain, or always use the same domain (either with, or without www.)

nl-x
  • 11,762
  • 7
  • 33
  • 61
  • I will try passing the session ID around in the test scenario and let you know the result as soon as I hear from the user with the problem. But if I remember correctly the --enable-trans-sid option was disabled because Google would index the same pages multiple times with different PHPSESSID values in the URL. – Jan-Henk May 29 '13 at 09:13
  • @Jan-Henk that is surprising. I would guess the Google crawler bots are cookie-enabled. And thus would prevent PHP of using the SID in the URLS. – nl-x May 29 '13 at 09:16
  • This change was made about 5 years ago, so it could be different right now. But we never had any problems with session data until this last month or so. – Jan-Henk May 29 '13 at 09:32
  • The code is 5 years old, but the issue started last month? That is worth mentioning :) ... Did you perhaps upgrade anything (Apache, PHP, firewall, proxy)? Is it a specific IE version issue? (perhaps only the users with the newest IE?) – nl-x May 29 '13 at 09:36
  • I did mention it in the OP :) I asked the hosting provider if anything had changed that could lead to these problems, but they said no. Furthermore it is only users with IE, but not all users with IE. I have confirmed reports for IE7 and IE9, but because I cannot replicate the problem myself I cannot say for certain there are no problems with other versions of IE. – Jan-Henk May 29 '13 at 09:39
  • I will ask the user to capture the network data for the test scenario with the F12 developer tools. Hopefully I can find something in there. – Jan-Henk May 29 '13 at 09:45
  • @Jan-Henk also see my edit. Maybe even log `$_SERVER['HTTP_HOST']` to your text file. – nl-x May 29 '13 at 09:50
  • I asked the user to capture the network data. After that I will look into the cookie domain. But if the requests from the user change the WWW part this will already be visible from the captured network data. – Jan-Henk May 29 '13 at 09:57
  • After capturing the network data I figured out that users with problems had Chrome Frame installed. With this extra bit of information I found out what the problem was, I have explained this in an answer of my own. But thanks for your help. – Jan-Henk May 30 '13 at 18:59
-1

First of all, you should verify your php.ini session configuration, especially cookie duration. Add section to your question. Install Fiddler on a client which is giving you the error and produce a full http dump of the session. This should be help you to track down the problem easily.

Ghigo
  • 2,312
  • 1
  • 18
  • 19
  • cookie duration/configuration is handled in the comments already. IE F12 developer tools will do. fiddler is not necessary. – nl-x May 29 '13 at 09:33
  • Relevant informations should be in question and not in comments. By the way, I see no php.ini section in comments. IE developer tools cannot save a complete request log. – Ghigo May 29 '13 at 09:39