1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26: 27: 28: 29: 30: 31: 32: 33: 34: 35:
36: Yii::import('application.components.ThemeGenerator.LoginThemeHelper');
37: 38: 39: 40: 41:
42: class CommonSiteControllerBehavior extends CBehavior {
43:
44: 45: 46: 47: 48:
49: public function login (LoginForm $model, $isMobile=false){
50:
51: $model->attributes = $_POST['LoginForm'];
52: Session::cleanUpSessions();
53:
54: $ip = $this->owner->getRealIp();
55:
56: $userModel = $model->getUser();
57: $isRealUser = $userModel instanceof User;
58: $effectiveUsername = $isRealUser ? $userModel->username : $model->username;
59: $isActiveUser = $isRealUser && $userModel->status == User::STATUS_ACTIVE;
60: 61:
62: Yii::app()->db->createCommand(
63: 'UPDATE x2_sessions SET status=status-1,lastUpdated=:time WHERE user=:name AND
64: CAST(IP AS CHAR)=:ip AND status BETWEEN -2 AND 0')
65: ->bindValues(
66: array(':time' => time(), ':name' => $effectiveUsername, ':ip' => $ip))
67: ->execute();
68:
69: $activeUser = Yii::app()->db->createCommand()
70: ->select('username')
71: ->from('x2_users')
72: ->where('username=:name AND status=1', array(':name' => $model->username))
73: ->limit(1)
74: ->queryScalar();
75:
76: if(isset($_SESSION['sessionId']))
77: $sessionId = $_SESSION['sessionId'];
78: else
79: $sessionId = $_SESSION['sessionId'] = session_id();
80:
81: $session = X2Model::model('Session')->findByPk($sessionId);
82:
83: 84:
85: $badAttemptsRefreshTimeout = 900;
86: $maxFailedLoginAttemptsPerIP = 100;
87: $maxLoginsBeforeCaptcha = 5;
88:
89: $this->pruneTimedOutBans ($badAttemptsRefreshTimeout);
90: $failedLoginRecord = FailedLogins::model()->findActiveByIp ($ip);
91: $badAttemptsWithThisIp = ($failedLoginRecord) ? $failedLoginRecord->attempts : 0;
92: if ($badAttemptsWithThisIp >= $maxFailedLoginAttemptsPerIP) {
93: $this->recordFailedLogin ($ip);
94: throw new CHttpException (403, Yii::t('app',
95: 'You are not authorized to use this application'));
96: }
97:
98: if ($session === null) {
99: $session = new Session;
100: $session->id = $sessionId;
101: $session->user = $model->getSessionUserName();
102: $session->lastUpdated = time();
103: $session->status = 0;
104: $session->IP = $ip;
105: } else {
106: $session->lastUpdated = time();
107: $session->user = $model->getSessionUserName();
108: }
109:
110: if($isActiveUser === false){
111: $model->verifyCode = '';
112: $model->validate ();
113: $this->recordFailedLogin ($ip);
114: $session->save();
115: if ($badAttemptsWithThisIp + 1 >= $maxFailedLoginAttemptsPerIP) {
116: throw new CHttpException (403, Yii::t('app',
117: 'You are not authorized to use this application'));
118: } else if ($badAttemptsWithThisIp >= $maxLoginsBeforeCaptcha - 1) {
119: $model->useCaptcha = true;
120: $model->setScenario('loginWithCaptcha');
121: $session->status = -2;
122: }
123: }else{
124: if($model->validate() && $model->login()){
125:
126: if($model->rememberMe){
127: foreach(array('username','rememberMe') as $attr) {
128: $cookieName = CHtml::resolveName ($model, $attr);
129: $cookie = new CHttpCookie(
130: $cookieName, $model->$attr);
131: $cookie->expire = time () + 2592000;
132: Yii::app()->request->cookies[$cookieName] = $cookie;
133: }
134: }else{
135: foreach(array('username','rememberMe') as $attr) {
136:
137: AuxLib::clearCookie(CHtml::resolveName($model, $attr));
138: }
139: }
140:
141:
142:
143: $isAdmin = Yii::app()->user->checkAccess('AdminIndex');
144: if($isAdmin && !$isMobile) {
145: $this->owner->attachBehavior('updaterBehavior', new UpdaterBehavior);
146: $this->owner->checkUpdates();
147: } else
148: Yii::app()->session['versionCheck'] = true;
149:
150: $session->status = 1;
151: $session->save();
152: SessionLog::logSession($model->username, $sessionId, 'login');
153: $_SESSION['playLoginSound'] = true;
154:
155: if(YII_UNIT_TESTING && defined ('X2_DEBUG_EMAIL') && X2_DEBUG_EMAIL)
156: Yii::app()->session['debugEmailWarning'] = 1;
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167: LoginThemeHelper::login();
168:
169: if ($isMobile) {
170: $this->owner->redirect($this->owner->createUrl('/mobile/home'));
171: } else {
172: if(Yii::app()->user->returnUrl == '/site/index') {
173: $this->owner->redirect(array('/site/index'));
174: } else {
175:
176: $this->owner->redirect(Yii::app()->user->returnUrl);
177: }
178: }
179:
180:
181: } else{
182: $model->verifyCode = '';
183: $this->recordFailedLogin ($ip);
184: $session->save();
185:
186: if ($badAttemptsWithThisIp + 1 >= $maxFailedLoginAttemptsPerIP) {
187: throw new CHttpException (403, Yii::t('app',
188: 'You are not authorized to use this application'));
189: } else if ($badAttemptsWithThisIp >= $maxLoginsBeforeCaptcha - 1) {
190: $model->useCaptcha = true;
191: $model->setScenario('loginWithCaptcha');
192: $session->status = -2;
193: }
194: }
195: }
196: $model->rememberMe = false;
197: }
198:
199: 200: 201:
202: protected function loginRequiresCaptcha() {
203: if (isset($_SESSION['sessionId'])) {
204: $failedLoginRecord = FailedLogins::model()->findActiveByIp ($this->owner->getRealIp());
205: $badAttemptsWithThisIp = ($failedLoginRecord) ? $failedLoginRecord->attempts : 0;
206:
207: $maxLoginsBeforeCaptcha = 5;
208:
209:
210: return $badAttemptsWithThisIp >= $maxLoginsBeforeCaptcha;
211: }
212: }
213:
214: public function recordFailedLogin($ip) {
215: $record = FailedLogins::model()->findActiveByIp ($ip);
216: if ($record) {
217: $record->attempts++;
218: } else {
219: $record = new FailedLogins;
220: $record->IP = $ip;
221: $record->attempts = 1;
222: }
223: $record->lastAttempt = time();
224: $record->save();
225: }
226:
227: 228: 229: 230:
231: private function pruneTimedOutBans ($badAttemptsRefreshTimeout) {
232: Yii::app()->db->createCommand()
233: ->update (
234: 'x2_failed_logins',
235: array('active' => 0),
236: 'active = 1 AND lastAttempt < :timeout',
237: array(':timeout' => time() - ($badAttemptsRefreshTimeout * 60))
238: );
239: }
240:
241:
242: }
243:
244: