/** * Override the singleton for unit testing * @param SessionManager|null $manager * @return \\ScopedCallback|null */ public static function setSessionManagerSingleton(SessionManager $manager = null) { session_write_close(); $rInstance = new \ReflectionProperty(SessionManager::class, 'instance'); $rInstance->setAccessible(true); $rGlobalSession = new \ReflectionProperty(SessionManager::class, 'globalSession'); $rGlobalSession->setAccessible(true); $rGlobalSessionRequest = new \ReflectionProperty(SessionManager::class, 'globalSessionRequest'); $rGlobalSessionRequest->setAccessible(true); $oldInstance = $rInstance->getValue(); $reset = [[$rInstance, $oldInstance], [$rGlobalSession, $rGlobalSession->getValue()], [$rGlobalSessionRequest, $rGlobalSessionRequest->getValue()]]; $rInstance->setValue($manager); $rGlobalSession->setValue(null); $rGlobalSessionRequest->setValue(null); if ($manager && PHPSessionHandler::isInstalled()) { PHPSessionHandler::install($manager); } return new \ScopedCallback(function () use(&$reset, $oldInstance) { foreach ($reset as &$arr) { $arr[0]->setValue($arr[1]); } if ($oldInstance && PHPSessionHandler::isInstalled()) { PHPSessionHandler::install($oldInstance); } }); }
public function testGetGlobalSession() { $context = \RequestContext::getMain(); if (!PHPSessionHandler::isInstalled()) { PHPSessionHandler::install(SessionManager::singleton()); } $rProp = new \ReflectionProperty('MediaWiki\\Session\\PHPSessionHandler', 'instance'); $rProp->setAccessible(true); $handler = \TestingAccessWrapper::newFromObject($rProp->getValue()); $oldEnable = $handler->enable; $reset[] = new \ScopedCallback(function () use($handler, $oldEnable) { if ($handler->enable) { session_write_close(); } $handler->enable = $oldEnable; }); $reset[] = TestUtils::setSessionManagerSingleton($this->getManager()); $handler->enable = true; $request = new \FauxRequest(); $context->setRequest($request); $id = $request->getSession()->getId(); session_id(''); $session = SessionManager::getGlobalSession(); $this->assertSame($id, $session->getId()); session_id('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); $session = SessionManager::getGlobalSession(); $this->assertSame('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', $session->getId()); $this->assertSame('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', $request->getSession()->getId()); session_write_close(); $handler->enable = false; $request = new \FauxRequest(); $context->setRequest($request); $id = $request->getSession()->getId(); session_id(''); $session = SessionManager::getGlobalSession(); $this->assertSame($id, $session->getId()); session_id('xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'); $session = SessionManager::getGlobalSession(); $this->assertSame($id, $session->getId()); $this->assertSame($id, $request->getSession()->getId()); }
/** * @dataProvider provideHandlers * @param string $handler php serialize_handler to use */ public function testSessionHandling($handler) { $this->hideDeprecated('$_SESSION'); $reset[] = $this->getResetter($rProp); $this->setMwGlobals(array('wgSessionProviders' => array(array('class' => 'DummySessionProvider')), 'wgObjectCacheSessionExpiry' => 2)); $store = new \HashBagOStuff(); $logger = new \TestLogger(true, function ($m) { return preg_match('/^SessionBackend a{32} /', $m) ? null : $m; }); $manager = new SessionManager(array('store' => $store, 'logger' => $logger)); PHPSessionHandler::install($manager); $wrap = \TestingAccessWrapper::newFromObject($rProp->getValue()); $reset[] = new \ScopedCallback(array($wrap, 'setEnableFlags'), array($wrap->enable ? $wrap->warn ? 'warn' : 'enable' : 'disable')); $wrap->setEnableFlags('warn'); \MediaWiki\suppressWarnings(); ini_set('session.serialize_handler', $handler); \MediaWiki\restoreWarnings(); if (ini_get('session.serialize_handler') !== $handler) { $this->markTestSkipped("Cannot set session.serialize_handler to \"{$handler}\""); } // Session IDs for testing $sessionA = str_repeat('a', 32); $sessionB = str_repeat('b', 32); $sessionC = str_repeat('c', 32); // Set up garbage data in the session $_SESSION['AuthenticationSessionTest'] = 'bogus'; session_id($sessionA); session_start(); $this->assertSame(array(), $_SESSION); $this->assertSame($sessionA, session_id()); // Set some data in the session so we can see if it works. $rand = mt_rand(); $_SESSION['AuthenticationSessionTest'] = $rand; $expect = array('AuthenticationSessionTest' => $rand); session_write_close(); $this->assertSame(array(array(LogLevel::WARNING, 'Something wrote to $_SESSION!')), $logger->getBuffer()); // Screw up $_SESSION so we can tell the difference between "this // worked" and "this did nothing" $_SESSION['AuthenticationSessionTest'] = 'bogus'; // Re-open the session and see that data was actually reloaded session_start(); $this->assertSame($expect, $_SESSION); // Make sure session_reset() works too. if (function_exists('session_reset')) { $_SESSION['AuthenticationSessionTest'] = 'bogus'; session_reset(); $this->assertSame($expect, $_SESSION); } // Re-fill the session, then test that session_destroy() works. $_SESSION['AuthenticationSessionTest'] = $rand; session_write_close(); session_start(); $this->assertSame($expect, $_SESSION); session_destroy(); session_id($sessionA); session_start(); $this->assertSame(array(), $_SESSION); session_write_close(); // Test that our session handler won't clone someone else's session session_id($sessionB); session_start(); $this->assertSame($sessionB, session_id()); $_SESSION['id'] = 'B'; session_write_close(); session_id($sessionC); session_start(); $this->assertSame(array(), $_SESSION); $_SESSION['id'] = 'C'; session_write_close(); session_id($sessionB); session_start(); $this->assertSame(array('id' => 'B'), $_SESSION); session_write_close(); session_id($sessionC); session_start(); $this->assertSame(array('id' => 'C'), $_SESSION); session_destroy(); session_id($sessionB); session_start(); $this->assertSame(array('id' => 'B'), $_SESSION); // Test merging between Session and $_SESSION session_write_close(); $session = $manager->getEmptySession(); $session->set('Unchanged', 'setup'); $session->set('Unchanged, null', null); $session->set('Changed in $_SESSION', 'setup'); $session->set('Changed in Session', 'setup'); $session->set('Changed in both', 'setup'); $session->set('Deleted in Session', 'setup'); $session->set('Deleted in $_SESSION', 'setup'); $session->set('Deleted in both', 'setup'); $session->set('Deleted in Session, changed in $_SESSION', 'setup'); $session->set('Deleted in $_SESSION, changed in Session', 'setup'); $session->persist(); $session->save(); session_id($session->getId()); session_start(); $session->set('Added in Session', 'Session'); $session->set('Added in both', 'Session'); $session->set('Changed in Session', 'Session'); $session->set('Changed in both', 'Session'); $session->set('Deleted in $_SESSION, changed in Session', 'Session'); $session->remove('Deleted in Session'); $session->remove('Deleted in both'); $session->remove('Deleted in Session, changed in $_SESSION'); $session->save(); $_SESSION['Added in $_SESSION'] = '$_SESSION'; $_SESSION['Added in both'] = '$_SESSION'; $_SESSION['Changed in $_SESSION'] = '$_SESSION'; $_SESSION['Changed in both'] = '$_SESSION'; $_SESSION['Deleted in Session, changed in $_SESSION'] = '$_SESSION'; unset($_SESSION['Deleted in $_SESSION']); unset($_SESSION['Deleted in both']); unset($_SESSION['Deleted in $_SESSION, changed in Session']); session_write_close(); $this->assertEquals(array('Added in Session' => 'Session', 'Added in $_SESSION' => '$_SESSION', 'Added in both' => 'Session', 'Unchanged' => 'setup', 'Unchanged, null' => null, 'Changed in Session' => 'Session', 'Changed in $_SESSION' => '$_SESSION', 'Changed in both' => 'Session', 'Deleted in Session, changed in $_SESSION' => '$_SESSION', 'Deleted in $_SESSION, changed in Session' => 'Session'), iterator_to_array($session)); $session->clear(); $session->set(42, 'forty-two'); $session->set('forty-two', 42); $session->set('wrong', 43); $session->persist(); $session->save(); session_start(); $this->assertArrayHasKey('forty-two', $_SESSION); $this->assertSame(42, $_SESSION['forty-two']); $this->assertArrayHasKey('wrong', $_SESSION); unset($_SESSION['wrong']); session_write_close(); $this->assertEquals(array(42 => 'forty-two', 'forty-two' => 42), iterator_to_array($session)); // Test that write doesn't break if the session is invalid $session = $manager->getEmptySession(); $session->persist(); session_id($session->getId()); session_start(); $this->mergeMwGlobalArrayValue('wgHooks', array('SessionCheckInfo' => array(function (&$reason) { $reason = 'Testing'; return false; }))); $this->assertNull($manager->getSessionById($session->getId(), true), 'sanity check'); session_write_close(); $this->mergeMwGlobalArrayValue('wgHooks', array('SessionCheckInfo' => array())); $this->assertNotNull($manager->getSessionById($session->getId(), true), 'sanity check'); }
public function testResetIdOfGlobalSession() { if (!PHPSessionHandler::isInstalled()) { PHPSessionHandler::install(SessionManager::singleton()); } if (!PHPSessionHandler::isEnabled()) { $rProp = new \ReflectionProperty('MediaWiki\\Session\\PHPSessionHandler', 'instance'); $rProp->setAccessible(true); $handler = \TestingAccessWrapper::newFromObject($rProp->getValue()); $resetHandler = new \ScopedCallback(function () use($handler) { session_write_close(); $handler->enable = false; }); $handler->enable = true; } $backend = $this->getBackend(User::newFromName('UTSysop')); \TestingAccessWrapper::newFromObject($backend)->usePhpSessionHandling = true; TestUtils::setSessionManagerSingleton($this->manager); $manager = \TestingAccessWrapper::newFromObject($this->manager); $request = \RequestContext::getMain()->getRequest(); $manager->globalSession = $backend->getSession($request); $manager->globalSessionRequest = $request; session_id(self::SESSIONID); \MediaWiki\quietCall('session_start'); $backend->resetId(); $this->assertNotEquals(self::SESSIONID, $backend->getId()); $this->assertSame($backend->getId(), session_id()); session_write_close(); session_id(''); $this->assertNotSame($backend->getId(), session_id(), 'sanity check'); $backend->persist(); $this->assertSame($backend->getId(), session_id()); session_write_close(); }