Activate A Captcha After Of Several Times

Hi everyone

Every knows what happens if you set for three times wrong user/pass on gmail or anything else mailer account

Does anyone achieved that in Yii (how to set a model to do that) ?

I didn’t write or check a code about that but I want your opinion :)

I have done that, although the code is quite old now, so I won’t share the specifics.

There’s a field in the User model which tracks successive failed logins. It’s incremented if login fails and reset to zero if login succeeds.

There are config values which specify how many failed login attempts will trigger the display and requirement of a captcha image and how many failed login attempts will lock the account. It can only be unlocked by the user requesting a verification email or by an administrator.

Once the account is locked, the failed login field is no longer incremented; the user just receives a message stating that the account is locked, with a link to request an unlock email.

Hi Keith,

I thought something similar with you!

I have a more specific question:

This is about model rules. What is the best way to make the captcha required and check the validation on the second or third time?

Do I have to create a custom validator? or check the conditions on beforeValidate method?

Or There is already yii validator or anyway is there a best way to do that? (many many ‘or’ :) )

Thanks

Here are the relevant parts of the form model:




	public function rules()

	{

		return array(

			...

			array('email',		'checkRecaptchaRequired'),

			array('recaptcha', 	'checkRecaptcha'),

			...

		);

	}


	// Only checks if recaptcha required and was requested by system. Does not increment failed logins.

	// Sets error if required but not requested in form.

	public function checkRecaptchaRequired($attribute, $params)

	{

		if (!$this->hasErrors())

		{

			if ($this->_userIdentity === NULL)

				die('Internal error in validation.');


			$userRecord = $this->_userIdentity->getUserRecord();

			$max_attempts = Yii::app()->params['login']['attemptsUntilRecaptcha'];

			// Error if account required image validation but not requested by form.

			if ($userRecord && $userRecord->failed_login_attempts >= $max_attempts && $this->recaptcha === NULL)

			{

				$lastLoginText = $userRecord->last_successful_login === NULL ? 'your account was created' : 'your last successful login';

				$this->addError('recaptcha', 'Image verification is required.');

				$this->formMessage .= '<p>Your account now requires image verification as a result of ' . $max_attempts .

									  ' or more failed login attempts since ' . $lastLoginText .

									  '. The details you provided in this attempt have not been checked, and have not been counted ' .

									  ' as a failed login attempt. Please provide the text from the image and resubmit.';

			}

		}

	}


	public function checkRecaptcha($attribute, $params)

	{

		// Only check if valid user and image shown in form

		if ($this->_userIdentity !== NULL && $this->recaptcha !== NULL)

		{

			$userRecord = $this->_userIdentity->getUserRecord();

			if ($userRecord && $userRecord->failed_login_attempts >= Yii::app()->params['login']['attemptsUntilRecaptcha'])

			{

				Yii::import('ext.recaptcha.EReCaptchaCheck');

				if (!EReCaptchaCheck::check())

				{

					$this->addError($attribute, EReCaptchaCheck::$message);

					$this->_doIncrementFailedLogins = TRUE;

				}

			}

		}

	}


	// Returns boolean. Called after all validation and failed login incrementation.

	public function displayRecaptcha()

	{

		if ($this->_userIdentity !== NULL)

		{

			$userRecord = $this->_userIdentity->getUserRecord();

			if ($userRecord)

			{

				return $userRecord->failed_login_attempts >= Yii::app()->params['login']['attemptsUntilRecaptcha'];

			}

		}

		return FALSE;

	}




Again, this is old code. I would probably handle it differently now.

So, you used custom validators with micro-conception MVC architecture in the Model

Just wanted the your way or opinion mainly (even without your code!) :)

Thank you for sharing your opinion :)