Quash www subdomain to prevent duplicate sessions

This commit is contained in:
Kijin Sung 2017-02-13 13:55:47 +09:00
parent 256d078394
commit ba925150a3
3 changed files with 71 additions and 16 deletions

View file

@ -73,7 +73,7 @@ class Mobile
$uatype = $uahash . ':' . (self::$_ismobile ? '1' : '0'); $uatype = $uahash . ':' . (self::$_ismobile ? '1' : '0');
if ($cookie !== $uatype) if ($cookie !== $uatype)
{ {
setcookie('rx_uatype', $uatype, 0, RX_BASEURL); setcookie('rx_uatype', $uatype, 0, RX_BASEURL, Rhymix\Framework\Session::getDomain());
$_COOKIE['rx_uatype'] = $uatype; $_COOKIE['rx_uatype'] = $uatype;
} }

View file

@ -10,6 +10,8 @@ class Session
/** /**
* Properties for internal use only. * Properties for internal use only.
*/ */
protected static $_domain = false;
protected static $_subdomain = false;
protected static $_started = false; protected static $_started = false;
protected static $_autologin_key = false; protected static $_autologin_key = false;
protected static $_member_info = false; protected static $_member_info = false;
@ -758,6 +760,48 @@ class Session
$_SESSION['RHYMIX']['timezone'] = $timezone; $_SESSION['RHYMIX']['timezone'] = $timezone;
} }
/**
* Get session domain.
*
* @return string
*/
public static function getDomain()
{
if (self::$_domain || (self::$_domain = Config::get('session.domain')))
{
return self::$_domain;
}
else
{
self::$_domain = ini_get('session.cookie_domain') ?: preg_replace('/:\\d+$/', '', strtolower($_SERVER['HTTP_HOST']));
if (!strncmp(self::$_domain, 'www.', 4))
{
self::$_subdomain = self::$_domain;
self::$_domain = substr(self::$_domain, 4);
}
return self::$_domain;
}
}
/**
* Set session domain.
*
* @return bool
*/
public static function setDomain($domain)
{
if (self::$_started)
{
return false;
}
else
{
self::$_domain = $domain;
self::$_subdomain = false;
return true;
}
}
/** /**
* Mark the current session as trusted for a given duration. * Mark the current session as trusted for a given duration.
* *
@ -930,7 +974,7 @@ class Session
{ {
$lifetime = Config::get('session.lifetime'); $lifetime = Config::get('session.lifetime');
$refresh = Config::get('session.refresh') ?: 300; $refresh = Config::get('session.refresh') ?: 300;
$domain = Config::get('session.domain') ?: (ini_get('session.cookie_domain') ?: preg_replace('/:\\d+$/', '', $_SERVER['HTTP_HOST'])); $domain = self::getDomain();
$path = Config::get('session.path') ?: ini_get('session.cookie_path'); $path = Config::get('session.path') ?: ini_get('session.cookie_path');
return array($lifetime, $refresh, $domain, $path); return array($lifetime, $refresh, $domain, $path);
} }
@ -996,6 +1040,15 @@ class Session
$_COOKIE['rx_sesskey2'] = $_SESSION['RHYMIX']['keys'][$domain]['key2']; $_COOKIE['rx_sesskey2'] = $_SESSION['RHYMIX']['keys'][$domain]['key2'];
} }
// Delete keys from subdomain.
if (self::$_subdomain && !isset($_SESSION['RHYMIX']['keys'][self::$_subdomain]['deleted']))
{
setcookie(session_name(), session_id(), $lifetime, $path, $domain, false, false);
setcookie(session_name(), 'deleted', time() - 86400, $path, self::$_subdomain, false, false);
setcookie('rx_sesskey1', 'deleted', time() - 86400, $path, self::$_subdomain, false, false);
setcookie('rx_sesskey2', 'deleted', time() - 86400, $path, self::$_subdomain, false, false);
$_SESSION['RHYMIX']['keys'][self::$_subdomain]['deleted'] = true;
}
return true; return true;
} }

View file

@ -48,9 +48,11 @@ class SessionTest extends \Codeception\TestCase\Test
$this->assertTrue(isset($_COOKIE['rx_sesskey1'])); $this->assertTrue(isset($_COOKIE['rx_sesskey1']));
$this->assertTrue(isset($_COOKIE['rx_sesskey2'])); $this->assertTrue(isset($_COOKIE['rx_sesskey2']));
$this->assertNotEmpty($_SESSION['RHYMIX']['secret']); $this->assertNotEmpty($_SESSION['RHYMIX']['secret']);
$this->assertEquals($_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1'], $_COOKIE['rx_sesskey1']); $this->assertEquals($_SESSION['RHYMIX']['keys']['rhymix.org']['key1'], $_COOKIE['rx_sesskey1']);
$this->assertEquals($_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2'], $_COOKIE['rx_sesskey2']); $this->assertEquals($_SESSION['RHYMIX']['keys']['rhymix.org']['key2'], $_COOKIE['rx_sesskey2']);
$this->assertEquals(0, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['trusted']); $this->assertEquals(0, $_SESSION['RHYMIX']['keys']['rhymix.org']['trusted']);
$this->assertFalse(isset($_SESSION['RHYMIX']['keys']['www.rhymix.org']['started']));
$this->assertTrue(isset($_SESSION['RHYMIX']['keys']['www.rhymix.org']['deleted']));
$session_secret = $_SESSION['RHYMIX']['secret']; $session_secret = $_SESSION['RHYMIX']['secret'];
Rhymix\Framework\Session::close(); Rhymix\Framework\Session::close();
@ -90,7 +92,7 @@ class SessionTest extends \Codeception\TestCase\Test
// Test initial transition from HTTP to HTTPS. // Test initial transition from HTTP to HTTPS.
session_start(); session_start();
unset($_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2']); unset($_SESSION['RHYMIX']['keys']['rhymix.org']['key2']);
unset($_COOKIE['rx_sesskey2']); unset($_COOKIE['rx_sesskey2']);
session_write_close(); session_write_close();
$this->assertTrue(@Rhymix\Framework\Session::start()); $this->assertTrue(@Rhymix\Framework\Session::start());
@ -139,17 +141,17 @@ class SessionTest extends \Codeception\TestCase\Test
{ {
@Rhymix\Framework\Session::start(); @Rhymix\Framework\Session::start();
$session_secret = $_SESSION['RHYMIX']['secret']; $session_secret = $_SESSION['RHYMIX']['secret'];
$key1 = $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1']; $key1 = $_SESSION['RHYMIX']['keys']['rhymix.org']['key1'];
$key2 = $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2']; $key2 = $_SESSION['RHYMIX']['keys']['rhymix.org']['key2'];
$_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1_time'] = time() - 3600; $_SESSION['RHYMIX']['keys']['rhymix.org']['key1_time'] = time() - 3600;
$_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2_time'] = time() - 3600; $_SESSION['RHYMIX']['keys']['rhymix.org']['key2_time'] = time() - 3600;
Rhymix\Framework\Session::close(); Rhymix\Framework\Session::close();
@Rhymix\Framework\Session::start(); @Rhymix\Framework\Session::start();
$this->assertNotEquals($key1, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1']); $this->assertNotEquals($key1, $_SESSION['RHYMIX']['keys']['rhymix.org']['key1']);
$this->assertNotEquals($key2, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2']); $this->assertNotEquals($key2, $_SESSION['RHYMIX']['keys']['rhymix.org']['key2']);
$this->assertEquals($key1, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key1_prev']); $this->assertEquals($key1, $_SESSION['RHYMIX']['keys']['rhymix.org']['key1_prev']);
$this->assertEquals($key2, $_SESSION['RHYMIX']['keys']['www.rhymix.org']['key2_prev']); $this->assertEquals($key2, $_SESSION['RHYMIX']['keys']['rhymix.org']['key2_prev']);
$this->assertEquals($session_secret, $_SESSION['RHYMIX']['secret']); $this->assertEquals($session_secret, $_SESSION['RHYMIX']['secret']);
Rhymix\Framework\Session::close(); Rhymix\Framework\Session::close();
} }
@ -231,9 +233,9 @@ class SessionTest extends \Codeception\TestCase\Test
{ {
@Rhymix\Framework\Session::start(); @Rhymix\Framework\Session::start();
$_SESSION['RHYMIX']['keys']['www.rhymix.org']['trusted'] = 0; $_SESSION['RHYMIX']['keys']['rhymix.org']['trusted'] = 0;
$this->assertFalse(Rhymix\Framework\Session::isTrusted()); $this->assertFalse(Rhymix\Framework\Session::isTrusted());
$_SESSION['RHYMIX']['keys']['www.rhymix.org']['trusted'] = time() + 300; $_SESSION['RHYMIX']['keys']['rhymix.org']['trusted'] = time() + 300;
$this->assertTrue(Rhymix\Framework\Session::isTrusted()); $this->assertTrue(Rhymix\Framework\Session::isTrusted());
Rhymix\Framework\Session::close(); Rhymix\Framework\Session::close();