Exemplo n.º 1
0
 /**
  * Logs this member out.
  */
 public function logOut()
 {
     $this->extend('beforeMemberLoggedOut');
     Session::clear("loggedInAs");
     if (Member::config()->login_marker_cookie) {
         Cookie::set(Member::config()->login_marker_cookie, null, 0);
     }
     Session::destroy();
     $this->extend('memberLoggedOut');
     // Clears any potential previous hashes for this member
     RememberLoginHash::clear($this, Cookie::get('alc_device'));
     Cookie::set('alc_enc', null);
     // // Clear the Remember Me cookie
     Cookie::force_expiry('alc_enc');
     Cookie::set('alc_device', null);
     Cookie::force_expiry('alc_device');
     // Switch back to live in order to avoid infinite loops when
     // redirecting to the login screen (if this login screen is versioned)
     Session::clear('readingMode');
     $this->write();
     // Audit logging hook
     $this->extend('memberLoggedOut');
 }
 public function testRememberMeMultipleDevices()
 {
     $m1 = $this->objFromFixture('SilverStripe\\Security\\Member', 'noexpiry');
     // First device
     $m1->login(true);
     Cookie::set('alc_device', null);
     // Second device
     $m1->login(true);
     // Hash of first device
     $firstHash = RememberLoginHash::get()->filter('MemberID', $m1->ID)->First();
     $this->assertNotNull($firstHash);
     // Hash of second device
     $secondHash = RememberLoginHash::get()->filter('MemberID', $m1->ID)->Last();
     $this->assertNotNull($secondHash);
     // DeviceIDs are different
     $this->assertNotEquals($firstHash->DeviceID, $secondHash->DeviceID);
     // re-generates the hashes so we can get the tokens
     $firstHash->Hash = $firstHash->getNewHash($m1);
     $firstToken = $firstHash->getToken();
     $firstHash->write();
     $secondHash->Hash = $secondHash->getNewHash($m1);
     $secondToken = $secondHash->getToken();
     $secondHash->write();
     // Accessing the login page should show the user's name straight away
     $response = $this->get('Security/login', $this->session(), null, array('alc_enc' => $m1->ID . ':' . $firstToken, 'alc_device' => $firstHash->DeviceID));
     $message = _t('Member.LOGGEDINAS', "You're logged in as {name}.", array('name' => $m1->FirstName));
     $this->assertContains($message, $response->getBody());
     $this->session()->inst_set('loggedInAs', null);
     // Accessing the login page from the second device
     $response = $this->get('Security/login', $this->session(), null, array('alc_enc' => $m1->ID . ':' . $secondToken, 'alc_device' => $secondHash->DeviceID));
     $this->assertContains($message, $response->getBody());
     // Logging out from the second device - only one device being logged out
     RememberLoginHash::config()->update('logout_across_devices', false);
     $response = $this->get('Security/logout', $this->session(), null, array('alc_enc' => $m1->ID . ':' . $secondToken, 'alc_device' => $secondHash->DeviceID));
     $this->assertEquals(RememberLoginHash::get()->filter(array('MemberID' => $m1->ID, 'DeviceID' => $firstHash->DeviceID))->Count(), 1);
     // Logging out from any device when all login hashes should be removed
     RememberLoginHash::config()->update('logout_across_devices', true);
     $m1->login(true);
     $response = $this->get('Security/logout', $this->session());
     $this->assertEquals(RememberLoginHash::get()->filter('MemberID', $m1->ID)->Count(), 0);
 }
 public function inst_start($sid = null)
 {
     $path = Config::inst()->get('SilverStripe\\Control\\Session', 'cookie_path');
     if (!$path) {
         $path = Director::baseURL();
     }
     $domain = Config::inst()->get('SilverStripe\\Control\\Session', 'cookie_domain');
     $secure = Director::is_https() && Config::inst()->get('SilverStripe\\Control\\Session', 'cookie_secure');
     $session_path = Config::inst()->get('SilverStripe\\Control\\Session', 'session_store_path');
     $timeout = Config::inst()->get('SilverStripe\\Control\\Session', 'timeout');
     if (!session_id() && !headers_sent()) {
         if ($domain) {
             session_set_cookie_params($timeout, $path, $domain, $secure, true);
         } else {
             session_set_cookie_params($timeout, $path, null, $secure, true);
         }
         // Allow storing the session in a non standard location
         if ($session_path) {
             session_save_path($session_path);
         }
         // If we want a secure cookie for HTTPS, use a seperate session name. This lets us have a
         // seperate (less secure) session for non-HTTPS requests
         if ($secure) {
             session_name('SECSESSID');
         }
         if ($sid) {
             session_id($sid);
         }
         session_start();
         $this->data = isset($_SESSION) ? $_SESSION : array();
     }
     // Modify the timeout behaviour so it's the *inactive* time before the session expires.
     // By default it's the total session lifetime
     if ($timeout && !headers_sent()) {
         Cookie::set(session_name(), session_id(), $timeout / 86400, $path, $domain ? $domain : null, $secure, true);
     }
 }
 /**
  * Choose the stage the site is currently on.
  *
  * If $_GET['stage'] is set, then it will use that stage, and store it in
  * the session.
  *
  * if $_GET['archiveDate'] is set, it will use that date, and store it in
  * the session.
  *
  * If neither of these are set, it checks the session, otherwise the stage
  * is set to 'Live'.
  */
 public static function choose_site_stage()
 {
     // Check any pre-existing session mode
     $preexistingMode = Session::get('readingMode');
     // Determine the reading mode
     if (isset($_GET['stage'])) {
         $stage = ucfirst(strtolower($_GET['stage']));
         if (!in_array($stage, array(static::DRAFT, static::LIVE))) {
             $stage = static::LIVE;
         }
         $mode = 'Stage.' . $stage;
     } elseif (isset($_GET['archiveDate']) && strtotime($_GET['archiveDate'])) {
         $mode = 'Archive.' . $_GET['archiveDate'];
     } elseif ($preexistingMode) {
         $mode = $preexistingMode;
     } else {
         $mode = static::DEFAULT_MODE;
     }
     // Save reading mode
     Versioned::set_reading_mode($mode);
     // Try not to store the mode in the session if not needed
     if ($preexistingMode && $preexistingMode !== $mode || !$preexistingMode && $mode !== static::DEFAULT_MODE) {
         Session::set('readingMode', $mode);
     }
     if (!headers_sent() && !Director::is_cli()) {
         if (Versioned::get_stage() == 'Live') {
             // clear the cookie if it's set
             if (Cookie::get('bypassStaticCache')) {
                 Cookie::force_expiry('bypassStaticCache', null, null, false, true);
             }
         } else {
             // set the cookie if it's cleared
             if (!Cookie::get('bypassStaticCache')) {
                 Cookie::set('bypassStaticCache', '1', 0, null, null, false, true);
             }
         }
     }
 }
 /**
  * Check we can remove cookies and we can access their original values
  */
 public function testForceExpiry()
 {
     //load an existing cookie
     $cookieJar = new CookieJar(array('cookieExisting' => 'i woz here'));
     Injector::inst()->registerService($cookieJar, 'SilverStripe\\Control\\Cookie_Backend');
     //make sure it's available
     $this->assertEquals('i woz here', Cookie::get('cookieExisting'));
     //remove the cookie
     Cookie::force_expiry('cookieExisting');
     //check it's gone
     $this->assertEmpty(Cookie::get('cookieExisting'));
     //check we can get it's original value
     $this->assertEquals('i woz here', Cookie::get('cookieExisting', false));
     //check we can add a new cookie and remove it and it doesn't leave any phantom values
     Cookie::set('newCookie', 'i am new');
     //check it's set by not recieved
     $this->assertEquals('i am new', Cookie::get('newCookie'));
     $this->assertEmpty(Cookie::get('newCookie', false));
     //remove it
     Cookie::force_expiry('newCookie');
     //check it's neither set nor reveived
     $this->assertEmpty(Cookie::get('newCookie'));
     $this->assertEmpty(Cookie::get('newCookie', false));
 }
Exemplo n.º 6
0
 /**
  * Set an alternative database in a browser cookie,
  * with the cookie lifetime set to the browser session.
  * This is useful for integration testing on temporary databases.
  *
  * There is a strict naming convention for temporary databases to avoid abuse:
  * <prefix> (default: 'ss_') + tmpdb + <7 digits>
  * As an additional security measure, temporary databases will
  * be ignored in "live" mode.
  *
  * Note that the database will be set on the next request.
  * Set it to null to revert to the main database.
  * @param string $name
  */
 public static function set_alternative_database_name($name = null)
 {
     // Skip if CLI
     if (Director::is_cli()) {
         return;
     }
     if ($name) {
         if (!self::valid_alternative_database_name($name)) {
             throw new InvalidArgumentException(sprintf('Invalid alternative database name: "%s"', $name));
         }
         $key = Config::inst()->get('SilverStripe\\Security\\Security', 'token');
         if (!$key) {
             throw new LogicException('"Security.token" not found, run "sake dev/generatesecuretoken"');
         }
         if (!function_exists('mcrypt_encrypt')) {
             throw new LogicException('DB::set_alternative_database_name() requires the mcrypt PHP extension');
         }
         $key = md5($key);
         // Ensure key is correct length for chosen cypher
         $ivSize = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CFB);
         $iv = mcrypt_create_iv($ivSize);
         $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $key, $name, MCRYPT_MODE_CFB, $iv);
         // Set to browser session lifetime, and restricted to HTTP access only
         Cookie::set("alternativeDatabaseName", base64_encode($encrypted), 0, null, null, false, true);
         Cookie::set("alternativeDatabaseNameIv", base64_encode($iv), 0, null, null, false, true);
     } else {
         Cookie::force_expiry("alternativeDatabaseName", null, null, false, true);
         Cookie::force_expiry("alternativeDatabaseNameIv", null, null, false, true);
     }
 }