原文 http://www.yiiframework.com/wiki/339/show-captcha-after-n-unsuccessfull-attempts/
In this mini howto I would like to show how to add a required captcha field in the login form, after a defined number of unsuccessfull attempts. To do this, I will use the blog demo that you have in default Yii download package (path/to/yii/demos/blog).
在这篇文章中,我将展示如果在用户登陆失败若干次之后,要求用户输入验证码。我将用yii 自带的blog demo来做演示。
Basically, you need three things:
-
in the model, you have to add captcha field as a required field in the rules() method
-
in the controller, you have to create a different LoginForm model if number of unsuccessfull attempts are greater than N
-
in the view, you have to show captcha field if number of unsuccessfull attempts are greater than N
开始之前,你需要这三样东西:
- 在model中,你在rules()中加一个captcha的验证规则
- 在controller中,你要新建一个不同的LoginForm model,如果用户失败登陆的次数大于某个数N
- 在view中,你要把captcha展示出来,如果用户失败登陆的次数大于某个数N
In the LoginForm model, you can use 'scenario' to set different required fields, so:
在LoginForm model,中你可以用'scenario'来设置不同‘scenario’中需要启动的验证规则,如下所示
public function rules() { return array( // username and password are required array('username, password', 'required'), // rememberMe needs to be a boolean array('rememberMe', 'boolean'), // password needs to be authenticated array('password', 'authenticate'), // add these lines below array('username,password,verifyCode','required','on'=>'captchaRequired'), array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()), ); }
Moreover, add verifyCode as public property:
而且在model中,添加public property ,verifyCode
public $verifyCode;
In the view, add this code (show captcha field if scenario is set to 'captchaRequired', will see later):
在view中,添加下面的代码,(展示captcha如果model的scenario是'captchaRequired',之后我们会看到如何设置,model的‘scenario’)
if($model->scenario == 'captchaRequired'): <div class="row"> <?php echo CHtml::activeLabelEx($model,'verifyCode'); <div> <?php $this->widget('CCaptcha'); <?php echo CHtml::activeTextField($model,'verifyCode'); </div> <div class="hint">Please enter the letters as they are shown in the image above. <br/>Letters are not case-sensitive.</div> </div> <?php endif;
Now, the controller. First, add a property to set maximum allowed attempts and a counter that trace failed attempts time to time:
现在,在controller中,我们添加一个property来设置前面提到的登陆失败的次数N,在controller里是$attempts,同时添加一个counter来记录用户失败登陆的次数。
public $attempts = 5; // allowed 5 attempts public $counter;
then, add a private function that returns true if 'captchaRequired' session value is greater than number of failed attempts.
然后,添加一个private function capchaRequired(),只当‘captchaRequired’session 的值大于失败登陆的次数时,返回true.
private function captchaRequired() { return Yii::app()->session->itemAt('captchaRequired') >= $this->attempts; }
We will use this function to know if captcha is required or not. Now, remain to modify actionLogin() method:
我们可以用这个function来判断captcha是否需要。现在我们来修改actionLogin() method:
public function actionLogin() { $model = $this->captchaRequired()? new LoginForm('captchaRequired') : new LoginForm; // if it is ajax validation request if(isset($_POST['ajax']) && $_POST['ajax']==='login-form') { echo CActiveForm::validate($model); Yii::app()->end(); } // collect user input data if(isset($_POST['LoginForm'])) { $model->attributes=$_POST['LoginForm']; // validate user input and redirect to the previous page if valid if($model->validate() && $model->login()) $this->redirect(Yii::app()->user->returnUrl); else { $this->counter = Yii::app()->session->itemAt('captchaRequired') + 1; Yii::app()->session->add('captchaRequired',$this->counter); } } // display the login form $this->render('login',array('model'=>$model)); }
Note that:
- if function captchaRequired() returns true create LoginForm with scenario 'captchaRequired', else create LoginForm with default scenario. This is useful because in protected/models/LoginForm.php we have set two different required fields depending on scenario:
public function rules() { return array( array('username, password', 'required'), array('username,password,verifyCode','required','on'=>'captchaRequired'), [... missing code...] }
- if validation passes redirect to a specific page, but what if validation doesn't pass? In this case we increment the counter, then set a session named 'captchaRequired' with counter value, in this way:
- 如果验证通过了,我们跳转到特定的页面,如果验证失败了,我们怎么做呢,这种情况下我们需要让我们的counter递增,然后设置一个名为'captchaRequired'的session值,代码如下
if($model->validate() && $model->login()) $this->redirect(Yii::app()->user->returnUrl); else { $this->counter = Yii::app()->session->itemAt('captchaRequired') + 1; Yii::app()->session->add('captchaRequired',$this->counter); }
When 'captchaRequired' session will be equal to maximum allowed attempts (property $attempts) private function captchaRequired() will return true and then LoginForm('captchaRequired') will be created. With scenario set to 'captchaRequired' captcha will be show in the view:
当'captchaRequired' session 等于最大允许失败次数(property $attempts)时,private function captchaRequired()将会返回true,从而LoginForm('captchaRequired')将被create.在‘captchaRequired’ scenario下,captcha将显示出来,
if($model->scenario == 'captchaRequired'): // code to show captcha <?php endif;
Easy, uh? ;)
很容易哈~ , :)
引用
http://www.yiiframework.com/forum/index.php/topic/21561-captcha-custom-validation

本文介绍如何在Yii框架中实现登录失败多次后显示验证码的功能。主要分为三步:在模型中添加验证码验证规则;控制器中根据失败次数使用不同模型;视图中动态显示验证码。
951

被折叠的 条评论
为什么被折叠?



