Prevent "Failed to create..." warnings when session loading fails
[lhc/web/wiklou.git] / includes / session / SessionManager.php
index 0abec1b..81f8243 100644 (file)
@@ -24,7 +24,6 @@
 namespace MediaWiki\Session;
 
 use Psr\Log\LoggerInterface;
-use Psr\Log\LogLevel;
 use BagOStuff;
 use CachedBagOStuff;
 use Config;
@@ -168,7 +167,6 @@ final class SessionManager implements SessionManagerInterface {
                        $store = $options['store'];
                } else {
                        $store = \ObjectCache::getInstance( $this->config->get( 'SessionCacheType' ) );
-                       $store->setLogger( $this->logger );
                }
                $this->store = $store instanceof CachedBagOStuff ? $store : new CachedBagOStuff( $store );
 
@@ -204,6 +202,7 @@ final class SessionManager implements SessionManagerInterface {
                // of "no such ID"
                $key = wfMemcKey( 'MWSession', $id );
                if ( is_array( $this->store->get( $key ) ) ) {
+                       $create = false;
                        $info = new SessionInfo( SessionInfo::MIN_PRIORITY, [ 'id' => $id, 'idIsSafe' => true ] );
                        if ( $this->loadSessionInfoFromStore( $info, $request ) ) {
                                $session = $this->getSessionFromInfo( $info, $request );
@@ -298,6 +297,11 @@ final class SessionManager implements SessionManagerInterface {
        }
 
        public function getVaryHeaders() {
+               // @codeCoverageIgnoreStart
+               if ( defined( 'MW_NO_SESSION' ) && MW_NO_SESSION !== 'warn' ) {
+                       return [];
+               }
+               // @codeCoverageIgnoreEnd
                if ( $this->varyHeaders === null ) {
                        $headers = [];
                        foreach ( $this->getProviders() as $provider ) {
@@ -316,6 +320,11 @@ final class SessionManager implements SessionManagerInterface {
        }
 
        public function getVaryCookies() {
+               // @codeCoverageIgnoreStart
+               if ( defined( 'MW_NO_SESSION' ) && MW_NO_SESSION !== 'warn' ) {
+                       return [];
+               }
+               // @codeCoverageIgnoreEnd
                if ( $this->varyCookies === null ) {
                        $cookies = [];
                        foreach ( $this->getProviders() as $provider ) {
@@ -509,12 +518,14 @@ final class SessionManager implements SessionManagerInterface {
                }
 
                # Notify AuthPlugin
+               // @codeCoverageIgnoreStart
                $tmpUser = $user;
                $wgAuth->initUser( $tmpUser, true );
                if ( $tmpUser !== $user ) {
                        $logger->warning( __METHOD__ . ': ' .
                                get_class( $wgAuth ) . '::initUser() replaced the user object' );
                }
+               // @codeCoverageIgnoreEnd
 
                # Notify hooks (e.g. Newuserlog)
                \Hooks::run( 'AuthPluginAutoCreate', [ $user ] );
@@ -653,8 +664,14 @@ final class SessionManager implements SessionManagerInterface {
                                                // This is going to error out below, but we want to
                                                // provide a complete list.
                                                $retInfos[] = $info;
+                                       } else {
+                                               // Session load failed, so unpersist it from this request
+                                               $info->getProvider()->unpersistSession( $request );
                                        }
                                }
+                       } else {
+                               // Session load failed, so unpersist it from this request
+                               $info->getProvider()->unpersistSession( $request );
                        }
                }
 
@@ -953,6 +970,17 @@ final class SessionManager implements SessionManagerInterface {
         * @return Session
         */
        public function getSessionFromInfo( SessionInfo $info, WebRequest $request ) {
+               // @codeCoverageIgnoreStart
+               if ( defined( 'MW_NO_SESSION' ) ) {
+                       if ( MW_NO_SESSION === 'warn' ) {
+                               // Undocumented safety case for converting existing entry points
+                               $this->logger->error( 'Sessions are supposed to be disabled for this entry point' );
+                       } else {
+                               throw new \BadMethodCallException( 'Sessions are disabled for this entry point' );
+                       }
+               }
+               // @codeCoverageIgnoreEnd
+
                $id = $info->getId();
 
                if ( !isset( $this->allSessionBackends[$id] ) ) {
@@ -1066,96 +1094,6 @@ final class SessionManager implements SessionManagerInterface {
                self::$globalSessionRequest = null;
        }
 
-       /**
-        * Do a sanity check to make sure the session is not used from many different IP addresses
-        * and store some data for later sanity checks.
-        * FIXME remove this once SessionManager is considered stable
-        * @private For use in Setup.php only
-        * @param Session $session Defaults to the global session.
-        */
-       public function checkIpLimits( Session $session = null ) {
-               $session = $session ?: self::getGlobalSession();
-
-               try {
-                       $ip = $session->getRequest()->getIP();
-               } catch ( \MWException $e ) {
-                       return;
-               }
-               if ( $ip === '127.0.0.1' || \IP::isConfiguredProxy( $ip ) ) {
-                       return;
-               }
-               $now = time();
-
-               // Record (and possibly log) that the IP is using the current session.
-               // Don't touch the stored data unless we are adding a new IP or re-adding an expired one.
-               // This is slightly inaccurate (when an existing IP is seen again, the expiry is not
-               // extended) but that shouldn't make much difference and limits the session write frequency
-               // to # of IPs / $wgSuspiciousIpExpiry.
-               $data = $session->get( 'SessionManager-ip', [] );
-               if (
-                       !isset( $data[$ip] )
-                       || $data[$ip] < $now
-               ) {
-                       $data[$ip] = time() + $this->config->get( 'SuspiciousIpExpiry' );
-                       foreach ( $data as $key => $expires ) {
-                               if ( $expires < $now ) {
-                                       unset( $data[$key] );
-                               }
-                       }
-                       $session->set( 'SessionManager-ip', $data );
-
-                       $logger = \MediaWiki\Logger\LoggerFactory::getInstance( 'session-ip' );
-                       $logLevel = count( $data ) >= $this->config->get( 'SuspiciousIpPerSessionLimit' )
-                               ? LogLevel::WARNING : ( count( $data ) === 1 ? LogLevel::DEBUG : LogLevel::INFO );
-                       $logger->log(
-                               $logLevel,
-                               'Same session used from {count} IPs',
-                               [
-                                       'count' => count( $data ),
-                                       'ips' => $data,
-                                       'session' => $session->getId(),
-                                       'user' => $session->getUser()->getName(),
-                                       'persistent' => $session->isPersistent(),
-                               ]
-                       );
-               }
-
-               // Now do the same thing globally for the current user.
-               // We are using the object cache and assume it is shared between all wikis of a farm,
-               // and further assume that the same name belongs to the same user on all wikis. (It's either
-               // that or a central ID lookup which would mean an extra SQL query on every request.)
-               if ( $session->getUser()->isLoggedIn() ) {
-                       $userKey = 'SessionManager-ip:' . md5( $session->getUser()->getName() );
-                       $data = $this->store->get( $userKey ) ?: [];
-                       if (
-                               !isset( $data[$ip] )
-                               || $data[$ip] < $now
-                       ) {
-                               $data[$ip] = time() + $this->config->get( 'SuspiciousIpExpiry' );
-                               foreach ( $data as $key => $expires ) {
-                                       if ( $expires < $now ) {
-                                               unset( $data[$key] );
-                                       }
-                               }
-                               $this->store->set( $userKey, $data, $this->config->get( 'SuspiciousIpExpiry' ) );
-                               $logger = \MediaWiki\Logger\LoggerFactory::getInstance( 'session-ip' );
-                               $logLevel = count( $data ) >= $this->config->get( 'SuspiciousIpPerUserLimit' )
-                                       ? LogLevel::WARNING : ( count( $data ) === 1 ? LogLevel::DEBUG : LogLevel::INFO );
-                               $logger->log(
-                                       $logLevel,
-                                       'Same user had sessions from {count} IPs',
-                                       [
-                                               'count' => count( $data ),
-                                               'ips' => $data,
-                                               'session' => $session->getId(),
-                                               'user' => $session->getUser()->getName(),
-                                               'persistent' => $session->isPersistent(),
-                                       ]
-                               );
-                       }
-               }
-       }
-
        /**@}*/
 
 }