I've written a moderately-sized Web application that utilizes MySQL and PHP5.

I have an on-going problem where Microsoft Internet Explorer 6 (IE6) and Microsoft Internet Explorer 7 (IE7) lose the PHP Session ID cookie (PHPSESSID). Of course, when this happens, the application loses track of the current user and the user is forced off the system and required to sign on again. As you can imagine, it's especially annoying to users.

I must be doing something wrong because if this problem were wide spread, I'm sure there would be a lot of grumbling by users and developers of PHP-driven Web applications.

Here's what I know about the issue. I've carefully monitored the HTTP traffic taking place between the Web application and the client browser using Fiddler2 and Live HTTP headers. Here's is what I've found:

Only in IE6 and IE7...

1. The browser accepts the PHPSESSID cookie just fine and users are able to sign on just fine and use the application for some undetermined period of time.

2. At some point, the browser loses or deletes the PHPSESSID cookie prematurely/unexpectedly. This is evidenced by the fact that the browser does not send the cookie back with the HTTP requests as it should even though the cookie was sent with subsequent requests. All of sudden, the PHPSESSID cookie is no more. I presume it is dropped or deleted by the browser, but I'm not sure why.

3. Mozilla Firefox works perfectly. I've not once had this problem in Firefox. This leads me to believe this issue is something browser specific or something about the PHPSESSID cookie that IE6 and IE7 do not like. I've tested this on many computers running IE6 and IE7 with various security and privacy settings and the results are no different. IE6 and IE7 drop the cookie unexpectedly while the session is still active.

Anyone have an leads on this issue? I've "googled" this issue it to death and there's nothing else out there that I can find.

Sincerely,

Ben Roberts
Azalea Technology

P.S. I do not want to go to including the session ID in URLs as I do not prefer that method of session tracking for a number of reasons.

Although I have not come across this problem before I can think of a couple of things that might be happening.

First of I would look in your code at any items that uses the session_start() function, as you could be accidently regenerating the existing session which would oviously reset the session_id().

On a side note if you are not checking whether a session exists before you create on the you can use

if(session_id()!=="")
        {
            //Session is not started try to start one
            @session_start();
            //Check to see if we successfully started are session
            if(session_id()!=="")
            {
                           //session didn't start raise and error trigger_error(E_USER_ERROR,SESSION_START_ERROR);
            }
        }

I did think of another reason but I have forgotten it, I wil post again later when I can remeber it (Sorry only on my second coffee of the day).

Urban

...I would look in your code at any items that uses the session_start() function, as you could be accidently regenerating the existing session which would oviously reset the session_id().
Urban

Thanks so much for your reply. You're the first.

One thing I've observed when looking at the HTTP activity is that my PHP Web application is not sending a new session ID until the browser makes a HTTP request that does not include the session ID.

I double checked this using fiddler2. Here is what I found. On the first response, the Web server sets the PHP session ID cookie when it sends the following as a part of it's HTTP response:

Set-Cookie: PHPSESSID=224c839dc3aab608a87d79897a67cec8; path=/

----------------- BEGIN HTTP TRAFFIC -----------------

Now fast forward in the HTTP exchange...the browser makes this good request which includes the PHP session cookie:

GET /lib/php/view.php?page=/viewer/reports HTTP/1.1
Accept: */*
Referer: http://www.resourcemethods.com/lib/php/controlpanel.php
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)
Host: www.resourcemethods.com
Proxy-Connection: Keep-Alive
Cookie: PHPSESSID=224c839dc3aab608a87d79897a67cec8;
active_user=59d6dc3f586b0151682d1515e46a536b846fd86475b62a69ab89fc986ef0ffd7; previous_session[y]=ca6399dc2db5b50066a887bfc10f987eee6a20c98aa144c5a6d087a4b9a7dce6; previous_session[x]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; searchfield[usermanager]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; searchtext[usermanager]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; sort[usermanager]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; direction[usermanager]=69d233d07bd8ffb9e38f82a9b663d1736603b6245b4f5ccc425be696e928b8c9; ipp[usermanager]=e13761bfad302b78d4a9d2c77aa65258d290e621611dd8685bfbc4d3cac17e14; pn[usermanager]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; searchfield[onlinelog]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; searchtext[onlinelog]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; sort[onlinelog]=50517731758448b018f473c2fe0945a05a9e8486ac6a67865fa4339a8201ede3; direction[onlinelog]=359cef6e51a1cd8b7c23a3b9ce129c2d57be213ab48dcd3835c8c2a61610ff97; ipp[onlinelog]=a744dd4fd8d11bac2fefe88c784128f13c3e409d33a3e56950defe127c83246b; pn[onlinelog]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7

Then, the server issues this good response:

HTTP/1.1 200 OK
Date: Sat, 19 May 2007 15:00:21 GMT
Server: Apache/2.0.54 (Debian GNU/Linux)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: previous_session[y]=71f37695bb37b0c84290becc231cbbf0f4b4616b48308db62a6170193cc23e4c; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: previous_session[x]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: searchfield[myreports]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: searchtext[myreports]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: sort[myreports]=6556d5b49cc04459a5c9a24b5cb1b32e18f4ba8311aeebbc580a29427557334c; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: direction[myreports]=359cef6e51a1cd8b7c23a3b9ce129c2d57be213ab48dcd3835c8c2a61610ff97; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: ipp[myreports]=70a52a59fb0d332e94e8dbe061836dac5875cb98b5abd2668123f6e2235db25a; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: pn[myreports]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

Then, an undetermined number of other requests and responses take place. All the responses contain the PHP session ID cookie. Here's the GOOD request and the response right before the issue takes place:

GET /lib/php/view.php?page=/viewer/reports HTTP/1.1
Accept: */*
Referer: http://www.resourcemethods.com/lib/php/controlpanel.php
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)
Host: www.resourcemethods.com
Proxy-Connection: Keep-Alive
Cookie: PHPSESSID=224c839dc3aab608a87d79897a67cec8; active_user=59d6dc3f586b0151682d1515e46a536b846fd86475b62a69ab89fc986ef0ffd7; previous_session[y]=ca6399dc2db5b50066a887bfc10f987eee6a20c98aa144c5a6d087a4b9a7dce6; previous_session[x]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; searchfield[usermanager]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; searchtext[usermanager]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; sort[usermanager]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; direction[usermanager]=69d233d07bd8ffb9e38f82a9b663d1736603b6245b4f5ccc425be696e928b8c9; ipp[usermanager]=e13761bfad302b78d4a9d2c77aa65258d290e621611dd8685bfbc4d3cac17e14; pn[usermanager]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; searchfield[onlinelog]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; searchtext[onlinelog]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; sort[onlinelog]=50517731758448b018f473c2fe0945a05a9e8486ac6a67865fa4339a8201ede3; direction[onlinelog]=359cef6e51a1cd8b7c23a3b9ce129c2d57be213ab48dcd3835c8c2a61610ff97; ipp[onlinelog]=a744dd4fd8d11bac2fefe88c784128f13c3e409d33a3e56950defe127c83246b; pn[onlinelog]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7

The response looks great...no reset of the PHP session ID cookie...

HTTP/1.1 200 OK
Date: Sat, 19 May 2007 15:00:21 GMT
Server: Apache/2.0.54 (Debian GNU/Linux)
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: previous_session[y]=71f37695bb37b0c84290becc231cbbf0f4b4616b48308db62a6170193cc23e4c; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: previous_session[x]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: searchfield[myreports]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: searchtext[myreports]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: sort[myreports]=6556d5b49cc04459a5c9a24b5cb1b32e18f4ba8311aeebbc580a29427557334c; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: direction[myreports]=359cef6e51a1cd8b7c23a3b9ce129c2d57be213ab48dcd3835c8c2a61610ff97; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: ipp[myreports]=70a52a59fb0d332e94e8dbe061836dac5875cb98b5abd2668123f6e2235db25a; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Set-Cookie: pn[myreports]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; expires=Sun, 20-May-2007 15:00:24 GMT; path=/
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

Then, the very next request, the browser makes this problematic HTTP get request and does not include the PHP session ID cookie. No "Set-Cookie:" was issued in the previous HTTP response. This seems to indicate to me that the browser has lost or deleted the cookie, so it does not include it w/ the request:

GET /lib/php/view.php?page=/manager/reports HTTP/1.1
Accept: */*
Accept-Language: en-us
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.0.3705; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)
Host: www.resourcemethods.com
Proxy-Connection: Keep-Alive
Cookie:
previous_session[y]=71f37695bb37b0c84290becc231cbbf0f4b4616b48308db62a6170193cc23e4c; previous_session[x]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; searchfield[usermanager]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; searchtext[usermanager]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; sort[usermanager]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; direction[usermanager]=69d233d07bd8ffb9e38f82a9b663d1736603b6245b4f5ccc425be696e928b8c9; ipp[usermanager]=e13761bfad302b78d4a9d2c77aa65258d290e621611dd8685bfbc4d3cac17e14; pn[usermanager]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; searchfield[onlinelog]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; searchtext[onlinelog]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; sort[onlinelog]=50517731758448b018f473c2fe0945a05a9e8486ac6a67865fa4339a8201ede3; direction[onlinelog]=359cef6e51a1cd8b7c23a3b9ce129c2d57be213ab48dcd3835c8c2a61610ff97; ipp[onlinelog]=a744dd4fd8d11bac2fefe88c784128f13c3e409d33a3e56950defe127c83246b; pn[onlinelog]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7; searchfield[myreports]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; searchtext[myreports]=b4ebdc4a94c01bce03e1e8eaffd2e8da6782ec9b8d8304c84f3396fb5ccfe923; sort[myreports]=6556d5b49cc04459a5c9a24b5cb1b32e18f4ba8311aeebbc580a29427557334c; direction[myreports]=359cef6e51a1cd8b7c23a3b9ce129c2d57be213ab48dcd3835c8c2a61610ff97; ipp[myreports]=70a52a59fb0d332e94e8dbe061836dac5875cb98b5abd2668123f6e2235db25a; pn[myreports]=3ecdf277d4c8fd059b75be30575cbc9b9e4050803f972aad3539e73cc032b0d7

Of course, here the server responds back as you would expect by trying to set a new PHP session ID cookie in the browser:

HTTP/1.1 302 Found
Date: Sat, 19 May 2007 15:00:29 GMT
Server: Apache/2.0.54 (Debian GNU/Linux)
Set-Cookie: PHPSESSID=3184bd3793023e473a8a353013311906; path=/
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: previous_session[y]=e1c6910272766cb96a16be68145a9cc683533e640825cf1626d489e3c0aed34d; expires=Sun, 20-May-2007 15:00:29 GMT; path=/
Set-Cookie: previous_session[x]=90779e07d35318318d5cf02a33c6e7f429d172e7afd6acebb5f1392ff136edc0; expires=Sun, 20-May-2007 15:00:29 GMT; path=/
Location: login.controller.php?action=logoff&status=010018
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html

----------------- END HTTP TRAFFIC -----------------

The HTTP activity above does not seem to be consistent w/ your theory about the Web application (server) regenerating/resetting the session ID because a "Cookie-Set: PHPSESSID=" command is NOT send as a part of the HTTP response before the browser sends a HTTP GET request that fails to include the PHPSESSID cookie.

After looking at the HTTP traffic, do you come to the same conclusion? Let me know.

Keep in mind that it's only IE6 and IE7 that have this behavior. Mozilla Firefox works flawlessly.

Sincerely,

Ben Roberts
Azalea Technology

I am as stupped as you are. The only thing that comes to mind is that IE sometimes has problem finsihes off writting session data and it is subsquently lost.

I think that it is quit well documented in the manual in the session_id() chapter. Besically in certian situations ie needs the session_write_close(); function but I think this problem is more when browsers are redirected in headers (Which i can see yours isn't.

If you solve this problem please post a solution and will keep my thinking hat on.

Urban

Is IE going through a Proxy?

Proxy-Connection: Keep-Alive

There is also the:

Connection: Close

response from the server. Thats odd for HTTP 1.1 .

If there is a proxy, it may be changing the HTTP Request outside what your fiddler picks up. Try testing without a proxy to single it down to IE fi you havent.

Is IE going through a Proxy?

Proxy-Connection: Keep-Alive

There is also the:

Connection: Close

response from the server. Thats odd for HTTP 1.1 .

If there is a proxy, it may be changing the HTTP Request outside what your fiddler picks up. Try testing without a proxy to single it down to IE fi you havent.

Yeah, I don't think IE is not going through a proxy like you are thinking. What you are seeing in the HTTP activity is actually a result of Fiddler fiddling with things.

It sounds like you have used Fiddler before. Take a look at your IE proxy settings. Under most circumstances, you should not have any proxy settings. Now, start the Fiddler application. Now, go look at your IE proxy settings again. You should note how Fiddler has modified the settings in order to listen to all the HTTP traffic taking place within IE.

Fiddler acts "like a proxy" so that it can look at all the HTTP traffic. It modifies the proxy configuration of IE and points the HTTP traffic to the loop back address (127.0.0.1:8888). This is how it listens to everything that is going on. The program title is actually "Fiddler - HTTP Debugging Proxy".

As for the "Connection: close", this does appear to be a part of the HTTP/1.1 standard. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html.

HTTP/1.1 defines the "close" connection option for the sender to signal that the connection will be closed after completion of the response. For example,

Connection: close

in either the request or the response header fields indicates that the connection SHOULD NOT be considered 'persistent' (section 8.1) after the current request/response is complete.

HTTP/1.1 applications that do not support persistent connections MUST include the "close" connection option in every message.

Let me know what you think.

Sincerely,

Ben Roberts
Azalea Technology

I am as stupped as you are. The only thing that comes to mind is that IE sometimes has problem finsihes off writting session data and it is subsquently lost.

I think that it is quit well documented in the manual in the session_id() chapter. Besically in certian situations ie needs the session_write_close(); function but I think this problem is more when browsers are redirected in headers (Which i can see yours isn't.

If you solve this problem please post a solution and will keep my thinking hat on.

Urban

Urban, you may be on to something here...

From time to time in the my Web application, I am doing some redirection using PHP's header function (http://www.php.net/header) and the Location header. Of course, this modifies the HTTP response header and causes the browser to redirect.

Maybe, to help IE, I need to make a call to session_write_close(); right before I call the header function in order to redirect.

Drum roll please... Okay, this was a good thought. I tried adding that function call, but it had no effect on the problem.

Again, I've included another sample of the HTTP traffic except for this time, I've included it as a file attachment.

Yeah, I don't think IE is not going through a proxy like you are thinking.

Oops...I meant...

Yeah, I don't think IE is going through a proxy like you are thinking.

Yeah, I don't think IE is not going through a proxy like you are thinking. What you are seeing in the HTTP activity is actually a result of Fiddler fiddling with things.

It sounds like you have used Fiddler before. Take a look at your IE proxy settings. Under most circumstances, you should not have any proxy settings. Now, start the Fiddler application. Now, go look at your IE proxy settings again. You should note how Fiddler has modified the settings in order to listen to all the HTTP traffic taking place within IE.

Fiddler acts "like a proxy" so that it can look at all the HTTP traffic. It modifies the proxy configuration of IE and points the HTTP traffic to the loop back address (127.0.0.1:8888). This is how it listens to everything that is going on. The program title is actually "Fiddler - HTTP Debugging Proxy".

As for the "Connection: close", this does appear to be a part of the HTTP/1.1 standard. See http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html.

Let me know what you think.

Sincerely,

Ben Roberts
Azalea Technology

I haven't used fiddler before. I recommend you use something like CAIN or Wireshark (formerly Ethereal). A "sniffer" that has to create a HTTP proxy that cannot fully implement HTTP 1.1 defeats the purpose.

Yes, Connection: close is defined in HTTP 1.1 specs. But HTTP 1.1 keeps a persistent TCP connection by default. Closing the connection means either the client or server does not support HTTP 1.1 fully.
The reason I said its odd is because both IE and Apache 2.x support HTTP 1.1 enough to keep a persistent connection. So its either a proxy that is fiddling (sorry... lame) with HTTP traffic or your application is setting the connection: close header.. (Unless you have some specific IE or Apache settings to do so, in which case you should test on other computers)

Usually, the simple cause of this problem is when you redirect to a new domain. The new domain can be www.example.com when you're on example.com, but from your HTTP dump (I haven't looked at the second) it seemed this wasn't the case. But knowing that it was from a proxy you still can't be sure...

Other than my advice to try and get a HTTP dump that isn't being altered by the application taking the dump, I'm stumped too.

The cookies is getting real long. IE has a shorter limit on cookies saved for a domain, I believe. Could be you're running out of space in IE. Should look that one up..

The cookies is getting real long. IE has a shorter limit on cookies saved for a domain, I believe. Could be you're running out of space in IE. Should look that one up..

Good ideas digital-ether.

The size of the cookie appears to be less than 1.5 KB. The published cookie size limit in IE is 4 KB (4,096 bytes).

See http://support.microsoft.com/kb/306070

There is a bit of data (because the values are encrypted), but it doesn't appear to be anywhere close to the 4 KB limit.

Yeah, I'll fire up Ethereal and setup a filter. Sounds like I need to download the new version since it has changed names.

The problem (IE6/IE7 dropping the cookie) also occurs on other PCs running IE6 or IE7 where no proxy is engaged. It also happens when fiddler is not running (i.e. not acting as a IE proxy) on my PC where I run IE6 and the latest version of Firefox.

I haven't used fiddler before. I recommend you use something like CAIN or Wireshark (formerly Ethereal). A "sniffer" that has to create a HTTP proxy that cannot fully implement HTTP 1.1 defeats the purpose.

We may be on the verge of a breakthrough here... =)

Here's a side note. Wow! Wireshark turned out to be much more unstable for me than the last release of Ethereal. =( I did not find anything the the HTTP sniffing results that we've not already seen. Also, it appears to truncate the HTTP information.

So, I started looking a little more closely at the cookie size issue. Windows measures file size in two ways: Size and Size on disk. Personally, I've always relied on the Size as the true measurement of the size of a file in Windows and NOT the the amount of space allocated for storage (cluster size) on the hard disk or Size on disk.

The Size on disk of my cookie file for this Web site reaches 4 KB (the limit published by Microsoft), but the Size never gets close.

Come to find out, IE6 and previous versions store some cookies in memory (session cookies) and some cookies on disk (persistent cookies). In this context, the PHPSESSID cookie is a session cookie. See http://support.microsoft.com/kb/260971

I've watched the Temporary Internet Files folder, and as soon as the Size on disk of the cookie for the Web site reaches 4 KB, then it appears that IE6 drops the PHPSESSID cookie as the first thing it throws overboard. I find this to be an interesting software behavior. Why throw away the PHP session ID cookie first as it would seem most critical? Maybe because it's a session cookie (less permanent...more volatile) and not a persistent cookie like the others. Let's hope so. I'd hope IE treats the ASP session cookie the same way.

A this stage in my research, it appears that IE6 and previous versions (http://support.microsoft.com/kb/260971) sum the space used in memory and on disk to determine the total cookie size when enforcing its cookie size limit. Unfortunately, it does not appear like there is a [good] way to measure the cookie use in memory like there is on disk.

References:
http://support.microsoft.com/kb/260971
http://support.microsoft.com/kb/223799

Presuming that cookie size (disk+memory) is the culprit in IE6/IE7, which seems like the most likely cause at this point, this spawns a whole other conversation about how to get the cookie size down in order to make the Web application more reliable in IE6/IE7 and balance security.

I've been in the practice of encrypting the values that I store in cookies. It always seemed to me that this enhances Web application security by not revealing some of the inner workings of the Web application even though the revelations might not be significant.

I've always considered cookies and their values as a potential platform for launching an attack on a Web-based application. So, I've always though it a best-practice for Web application security practice to encrypt cookie values.

Thoughts?

Well, it appears there is a total size (4 KB) and total number limit (20) per domain.

There's a way around the number limit by creating a cookie dictionary. I've done this with ASP in the past. It was not hard. I cannot find any help on Google about creating/manipulating cookie dictionaries in PHP.

Any ideas on how to implement a cookie dictionary like is possible in ASP (http://www.webcheatsheet.com/asp/cookies.php)?

Reference
http://support.microsoft.com/kb/306070

Presuming that cookie size (disk+memory) is the culprit in IE6/IE7, which seems like the most likely cause at this point, this spawns a whole other conversation about how to get the cookie size down in order to make the Web application more reliable in IE6/IE7 and balance security.

I've been in the practice of encrypting the values that I store in cookies. It always seemed to me that this enhances Web application security by not revealing some of the inner workings of the Web application even though the revelations might not be significant.

I've always considered cookies and their values as a potential platform for launching an attack on a Web-based application. So, I've always though it a best-practice for Web application security practice to encrypt cookie values.

Thoughts?

You could move your cookies to the database or the filesystem. This also removes the unnecessary HTTP bandwidth used in sending the cookies back to your server on each request.

You can get away with having just one session cookie, and one permanent cookie.
Both of these cookies are just hashes that point to the data saved in the database or filesystem...

eg: setting the data

<?php

$salt = 'longsecret...';
query("insert into http_clients ...");
setcookie('http_client_id', sha1(mysql_insert_id().$salt));

?>

eg: getting data

<?php

if ($http_client_id = isset($COOKIE['http_client_id']) ? $COOKIE['http_client_id'] : false) {

// got data in db for this client

$rows = query("
select *
from http_clients
where sha1( concat( id, '$salt' ) ) = '$http_client_id'
limit 1
");

} else {

// no setting for this client, send the cookie and stuff... 

}

?>

note: might have to cast() the integer "id" to "char"..

concat( cast(id, 'char'), '$salt' )

but I don't think mysql would care...

That way there is no way anyone viewing the HTTP traffic to know the settings saved for the user unless they figure out the secret $salt. You can also go a step further and salt with the sessionid and keep this sessionid in the db row for the user. That way you get random salts...

The only overhead is the mysql queries when inserting, updating and selecting the settings saved...
Or the filesystem access if you go with that..

Well, it appears there is a total size (4 KB) and total number limit (20) per domain.

There's a way around the number limit by creating a cookie dictionary. I've done this with ASP in the past. It was not hard. I cannot find any help on Google about creating/manipulating cookie dictionaries in PHP.

Any ideas on how to implement a cookie dictionary like is possible in ASP (http://www.webcheatsheet.com/asp/cookies.php)?

Reference
http://support.microsoft.com/kb/306070

You'd have to look at how ASP implements cookie dictionary in HTTP.
PHP has a feature as you probably know of parsing "HTTP params" with array syntax as arrays. I assume this is similar to what ASP does, but parses arrays inside cookie values..

What you can do is put all the settings into an array and then convert this array into a notation that saves the array indices and values such as with PHP's serialize function, or JSON for example.

You can then "unserialize" the cookie data when you retrieve it.

There is an overhead with methods such as serialize() and JSON that you can eliminate if you just use a simple notation such as url-encoded parameters...
eg: var1=value&var2=value2 and then parse that..

Note: This is a little bit of rant about Microsoft's implementation of RFC 2109 - HTTP State Management Mechanism, Section 6.3 Implementation Limits.

Leave it to Microsoft to implement some odd-ball interpretation of the RFC that pertains to cookies. The RFC uses the language at least not at most in reference to these limitations referring to them as a sort of lower limit not an upper limit.

With internet browsers for personal computers being the most robust user agents in terms of processor, memory and storage resources available to them, you would expect that PC browsers like Internet Explorer would implement a little more than the bare minimum when it comes to the RFC.

I guess I cannot blame Microsoft entirely since the RFC also states: "Applications should use as few and as small cookies as possible, and they should cope gracefully with the loss of a cookie."

Here's the portion of the RFC that pertains to limitations on cookies:

6.3 Implementation Limits

Practical user agent implementations have limits on the number and
size of cookies that they can store. In general, user agents' cookie
support should have no fixed limits. They should strive to store as
many frequently-used cookies as possible. Furthermore, general-use
user agents should provide each of the following minimum capabilities
individually, although not necessarily simultaneously:

* at least 300 cookies

* at least 4096 bytes per cookie (as measured by the size of the
characters that comprise the cookie non-terminal in the syntax
description of the Set-Cookie header)

* at least 20 cookies per unique host or domain name

User agents created for specific purposes or for limited-capacity
devices should provide at least 20 cookies of 4096 bytes, to ensure
that the user can interact with a session-based origin server.

The information in a Set-Cookie response header must be retained in
its entirety. If for some reason there is inadequate space to store
the cookie, it must be discarded, not truncated.

Applications should use as few and as small cookies as possible, and
they should cope gracefully with the loss of a cookie.

Reference
http://www.ietf.org/rfc/rfc2109.txt
http://support.microsoft.com/kb/306070

You could move your cookies to the database or the filesystem. This also removes the unnecessary HTTP bandwidth used in sending the cookies back to your server on each request...

Yeah, I'm wondering which is the lesser evil. With the prevalence of high-speed internet access, I'm thinking that less than 4 KB worth of cookie data being passed via HTTP isn't much of a concern at all when I consider the options of storing user preferences and selections. I really see three options...

Cookies
Pros
: places the majority of the resource consumption and work on bandwidth and the client PC and not on the Web application. This seems good for Web application performance.
Cons: must be supported/enabled in the user agent, limited storage space, varying implementations of the RFC, larger HTTP requests consume more bandwidth, vulnerable to modifications

Session
Pros
: places the majority of the resource consumption and work on the server and not the client, decreases work performed by the client PC, reduces the size of HTTP requests
Cons: vulnerable to hijacking, increases the work performed by the server which can become an issue w/ a multi-user application

Database & File System
Pros: no reliance on cookies or sessions which can be unreliable for various reasons and introduce security concerns
Cons: disk access and database reads/writes are typically some of the slowest and costliest computing operations

Thoughts? What's most common? What's the best balance between resource allocation (server/client processing, memory, disk and bandwidth) application performance and security for the most common case?

Yeah, I'm wondering which is the lesser evil. With the prevalence of high-speed internet access, I'm thinking that less than 4 KB worth of cookie data being passed via HTTP isn't much of a concern at all when I consider the options of storing user preferences and selections. I really see three options...

Cookies
Pros
: places the majority of the resource consumption and work on bandwidth and the client PC and not on the Web application. This seems good for Web application performance.
Cons: must be supported/enabled in the user agent, limited storage space, varying implementations of the RFC, larger HTTP requests consume more bandwidth, vulnerable to modifications

Session
Pros
: places the majority of the resource consumption and work on the server and not the client, decreases work performed by the client PC, reduces the size of HTTP requests
Cons: vulnerable to hijacking, increases the work performed by the server which can become an issue w/ a multi-user application

Database & File System
Pros: no reliance on cookies or sessions which can be unreliable for various reasons and introduce security concerns
Cons: disk access and database reads/writes are typically some of the slowest and costliest computing operations

Thoughts? What's most common? What's the best balance between resource allocation (server/client processing, memory, disk and bandwidth) application performance and security for the most common case?

I think you should sent the most frequently use stuff in cookies but less accessed preferences in the server's disk or db.

They thing about cookies is that they are "dumb", they get sent each time. Your application can choose when to retrieve a preference.

If your application already has a mysql connection, then it doesn't increase load if you use mysql to save user preferences. Creating the mysql connection is 90% of the load. A query, if simple selects and inserts, contribute less than 1% each.

Many thanks to digital-ether and UrbanSky. I appreciate all your help on this thread.

For anyone else who uses cookies in your Web apps (that's probably most everyone), don't waste hours of your life trying to figure out why Internet Explorer just unexpectedly loses track of your session (i.e. discards the PHPSESSID cookie).

It's probably the 20 cookies per domain or 4 KB size limit enforced by Internet Explorer. Firefox allows up to 50 cookies per domain so it usually works fine. Keep in mind that your PHP session cookie counts as one of the 20, so you really have 19 cookies at your disposal.

Again, big thanks to digital-ether for your help on this thread. Gracias!

commented: very interesting +2

Regarding your problem of IE dropping session id - I encountered this after my ISP upgraded the version of PHP to 4.4.6, although I cannot say 100% that this is the cause, just my suspicion.

Anyway, I had a major breakthrough yesterday when I set the following in my .php before the session_start():

ini_set('session.cookie_domain','.yourdomain.com');

Alternatively you can set session.cookie_domain to '.yourdomain.com' in the php.ini file.

After that, at least on IE6, the problem with sessions getting lost stopped!

If this helps you out, then great. Let me know, as I am unsure whether it solves the problem on IE7.

Thanks for the advice. I'll keep that in mind.

My issue was definitely the 20 cookie limit per domain (a strange and very conservative interpretation of Section 6.3 of RFC 2109) enforced by Internet Explorer 6/7 as well as earlier versions.

I am having this problem as well and from what I can tell it has something to do with IE not accepting the SESSION ID cookie from any domain that has a hostname in front of the domain name in the url. IE will accept the cookie and hold on to it if your url looks like this https://somedomain.com but not https://somehost.somedomain.com (aka https://www.mydomain.net). I have an application that I developed which uses SESSIONS and this is what I have discovered while deploying it. If the customer does not use a host name in front of the domain name in the URL then IE will use the cookie with no problems and it will not lose it util it expires. I would love to find a solution to this problem - any ideas?

compudude,

Believe it or not, I've seen this problem before. I know that IE6 does not like *some* special characters (not sure about the complete list of problematic characters) in the sub domain name portion of the URL such as underscores, etc.

What is the sub domain part of your URL? For example, I've experienced IE dropping and/or mishandling cookies with URLs like this:

https://some_host.somedomain.com

Note the underscore. I know it causes a problem for IE6. As I recall, it was especially a problem with HTTPS URLS. Obviously, URLS should conform to the RFC guidelines.

compudude,

Believe it or not, I've seen this problem before. I know that IE6 does not like *some* special characters (not sure about the complete list of problematic characters) in the sub domain name portion of the URL such as underscores, etc.

What is the sub domain part of your URL? For example, I've experienced IE dropping and/or mishandling cookies with URLs like this:

https://some_host.somedomain.com

Note the underscore. I know it causes a problem for IE6. As I recall, it was especially a problem with HTTPS URLS. Obviously, URLS should conform to the RFC guidelines.

brob5000....

THANK YOU..
THANK YOU..
THANK YOU..

I have been dealing with this problem for 2 weeks and was focused on p3p privacy report..

When I contact my internal webserver http://some_host.somedomain.com I was getting the blocked cookies and the privacy report issue.. I was searching for the problem in a different technology and finally found my way here when I started looking at a PHP workaround...

I signed up here with this site just to thank you!


THANKS A BUNCH!!!!!!!!!

Cliff

Cliff,

I'm glad I could help. It makes the many frustrating hours that spent trying to troubleshoot the issue seem a little less wasted.

Sincerely,
Ben

First of all, thank you for this thread. It was extremely helpful in diagnosing the issue I was experiencing.

Second I would like to add that this is not unique to PHP (PHPSESSID). Our application is served up by JBOSS, and the associated JSESSIONID was being lost when our application cookie became too large.

Just signed up to say those two things :)

Thanks for the help!

-
Carlos

Carlos,

You're welcome. I'm glad this thread was able to help. It makes me feel as though my time troubleshooting this issue was not wasted.

Kudos to brob5000 for running the discussion on this thread.

Now my main concern is, why does IE6/IE7 very often, if not always, drop the session information when the browser lies behind a proxy or proxy farm?

For example, a user of my app visits the site from, let's say, a nationwide proxy system from UAE or China.

Upon authenticating the user and setting his session to indicate that he is logged in, the session is immediately broken whenever he navigates on another link from the same website.

I don't think the 20 cookie limit per domain or 4kb size limit per cookie comes into play. Am I missing something here, or does the proxy mangle with the HTTP requests/responses?

(For the meantime, I'll just recommend Firefox to my visitors as a better alternative.)

Cheers to all,
O.J. Tibi

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.