/** * Displays the login page * @param object $formModel * @param bool $isMobile Whether this was called from mobile site controller */ public function login(LoginForm $model, $isMobile = false) { $model->attributes = $_POST['LoginForm']; // get user input data Session::cleanUpSessions(); $ip = $this->owner->getRealIp(); $userModel = $model->getUser(); $isRealUser = $userModel instanceof User; $effectiveUsername = $isRealUser ? $userModel->username : $model->username; $isActiveUser = $isRealUser && $userModel->status == User::STATUS_ACTIVE; /* increment count on every session with this user/IP, to prevent brute force attacks using session_id spoofing or whatever */ Yii::app()->db->createCommand('UPDATE x2_sessions SET status=status-1,lastUpdated=:time WHERE user=:name AND CAST(IP AS CHAR)=:ip AND status BETWEEN -2 AND 0')->bindValues(array(':time' => time(), ':name' => $effectiveUsername, ':ip' => $ip))->execute(); $activeUser = Yii::app()->db->createCommand()->select('username')->from('x2_users')->where('username=:name AND status=1', array(':name' => $model->username))->limit(1)->queryScalar(); // get the correctly capitalized username if (isset($_SESSION['sessionId'])) { $sessionId = $_SESSION['sessionId']; } else { $sessionId = $_SESSION['sessionId'] = session_id(); } $session = X2Model::model('Session')->findByPk($sessionId); /* get the number of failed login attempts from this IP within timeout interval. If the number of login attempts exceeds maximum, display captcha */ $badAttemptsRefreshTimeout = 900; $maxFailedLoginAttemptsPerIP = 100; $maxLoginsBeforeCaptcha = 5; $this->pruneTimedOutBans($badAttemptsRefreshTimeout); $failedLoginRecord = FailedLogins::model()->findActiveByIp($ip); $badAttemptsWithThisIp = $failedLoginRecord ? $failedLoginRecord->attempts : 0; if ($badAttemptsWithThisIp >= $maxFailedLoginAttemptsPerIP) { $this->recordFailedLogin($ip); throw new CHttpException(403, Yii::t('app', 'You are not authorized to use this application')); } // if this client has already tried to log in, increment their attempt count if ($session === null) { $session = new Session(); $session->id = $sessionId; $session->user = $model->getSessionUserName(); $session->lastUpdated = time(); $session->status = 0; $session->IP = $ip; } else { $session->lastUpdated = time(); $session->user = $model->getSessionUserName(); } if ($isActiveUser === false) { $model->verifyCode = ''; // clear captcha code $model->validate(); // validate captcha if it's being used $this->recordFailedLogin($ip); $session->save(); if ($badAttemptsWithThisIp + 1 >= $maxFailedLoginAttemptsPerIP) { throw new CHttpException(403, Yii::t('app', 'You are not authorized to use this application')); } else { if ($badAttemptsWithThisIp >= $maxLoginsBeforeCaptcha - 1) { $model->useCaptcha = true; $model->setScenario('loginWithCaptcha'); $session->status = -2; } } } else { if ($model->validate() && $model->login()) { // user successfully logged in if ($model->rememberMe) { foreach (array('username', 'rememberMe') as $attr) { // Expires in 30 days AuxLib::setCookie(CHtml::resolveName($model, $attr), $model->{$attr}, 2592000); } } else { foreach (array('username', 'rememberMe') as $attr) { // Remove the cookie if they unchecked the box AuxLib::clearCookie(CHtml::resolveName($model, $attr)); } } // We're not using the isAdmin parameter of the application // here because isAdmin in this context hasn't been set yet. $isAdmin = Yii::app()->user->checkAccess('AdminIndex'); if ($isAdmin && !$isMobile) { $this->owner->attachBehavior('updaterBehavior', new UpdaterBehavior()); $this->owner->checkUpdates(); // check for updates if admin } else { Yii::app()->session['versionCheck'] = true; } // ...or don't $session->status = 1; $session->save(); SessionLog::logSession($model->username, $sessionId, 'login'); $_SESSION['playLoginSound'] = true; if (YII_UNIT_TESTING && defined('X2_DEBUG_EMAIL') && X2_DEBUG_EMAIL) { Yii::app()->session['debugEmailWarning'] = 1; } // if ( isset($_POST['themeName']) ) { // $profile = X2Model::model('Profile')->findByPk(Yii::app()->user->id); // $profile->theme = array_merge( // $profile->theme, // ThemeGenerator::loadDefault( $_POST['themeName']) // ); // $profile->save(); // } LoginThemeHelper::login(); if ($isMobile) { $this->owner->redirect($this->owner->createUrl('/mobile/home')); } else { if (Yii::app()->user->returnUrl == '/site/index') { $this->owner->redirect(array('/site/index')); } else { // after login, redirect to wherever $this->owner->redirect(Yii::app()->user->returnUrl); } } } else { // login failed $model->verifyCode = ''; // clear captcha code $this->recordFailedLogin($ip); $session->save(); if ($badAttemptsWithThisIp + 1 >= $maxFailedLoginAttemptsPerIP) { throw new CHttpException(403, Yii::t('app', 'You are not authorized to use this application')); } else { if ($badAttemptsWithThisIp >= $maxLoginsBeforeCaptcha - 1) { $model->useCaptcha = true; $model->setScenario('loginWithCaptcha'); $session->status = -2; } } } } $model->rememberMe = false; }
/** * Saves a profile Theme to the cookies * @param string $themeName name of the theme to be set. */ public static function saveProfileTheme($themeName) { //Set a cookie for the profile theme set if ($themeName != ThemeGenerator::$defaultLight) { AuxLib::setCookie(self::PROFILE_COOKIE, $themeName, self::$cookieLength); } // Set a cookie for the login screen if (isset($_COOKIE[self::LOGIN_THEME_COOKIE])) { AuxLib::setCookie(self::LOGIN_THEME_COOKIE, $themeName, self::$cookieLength); } }