Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP, Session Cookies and Internet Explorer [duplicate]

Tags:

php

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.

like image 684
mpen Avatar asked Nov 11 '22 13:11

mpen


1 Answers

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.

like image 197
mpen Avatar answered Nov 15 '22 07:11

mpen