My users are having trouble logging into my site in Internet Explorer (10 and 11, perhaps older).
Through some trial and error, I discovered that IE is setting the PHPSESSID
cookie twice. This is visible by typing document.cookie
into the F12 developer toolbar.
Research suggests that this may be caused by having a "www." version and non-www version of the cookie. I'm not sure how to verify this, but I was hoping I could boycott the issue by setting the domain explicitly by calling session_set_cookie_params
.
Thus I have:
$host = $_SERVER['HTTP_HOST'];
if(substr($host, 0, 4) === 'www.') $host = substr($host, 4);
$colon = strrpos($host, ':');
if($colon !== false) $host = substr($host, 0, $colon);
session_set_cookie_params(0, '/', $host);
session_start();
I'm stripping the port too (developing on localhost:81) because that's what document.domain
returns.
Host is now simply localhost
(haven't tried on live site yet), and I can't log in at all in IE. Works fine in Firefox, does not work in Chrome.
How can I get PHP or the browser to share session cookies between the www subdomain and no subdomain versions of the site?
I tried throwing a dot in there per the related question:
$host = $_SERVER['HTTP_HOST'];
if(substr($host, 0, 4) === 'www.') $host = substr($host, 4);
$colon = strrpos($host, ':');
if($colon !== false) $host = substr($host, 0, $colon);
session_set_cookie_params(0, '/', '.'.$host);
session_start();
I dumped session_get_cookie_params()
to confirm it was set correctly. This does not appear to solve my issue either. The session keeps getting reset.
I wrote a function to parse out the cookie string manually, which handles dupes:
function parse_cookie_str($str = null) {
if ($str === null)
$str = array_key_exists('HTTP_COOKIE', $_SERVER)
? $_SERVER['HTTP_COOKIE']
: ''
;
$kvps = array_map('ltrim', explode(';', $str));
$cookies = array();
foreach ($kvps as $kvp) {
list ($name, $value) = explode('=', $kvp);
if (array_key_exists($name, $cookies)) {
if (!is_array($cookies[$name])) {
$cookies[$name] = array($cookies[$name]);
}
$cookies[$name][] = $value;
} else {
$cookies[$name] = $value;
}
}
return $cookies;
}
If PHPSESSID
is in there twice, we know something's wrong. The cookie does not appear to be deletable, so let's use some social engineering:
$cookies = parse_cookie_str();
$phpsessid = session_name();
if (
isset($cookies[$phpsessid])
&& is_array($cookies[$phpsessid])
) { // two or more PHPSESSIDs found
exit("Your session is corrupt. Please close your browser and try again.");
}
Now that the PHPSESSID
issue is fixed, I just need to force the users to one subdomain so that the issue doesn't come up again. This must be done before starting the session.
So far, this works.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With