0

I am trying to add captcha validation based on scenario, for which I am first retrieving number of failed attempts from database. For which I am using checkattempts() function. Based on the result I am displaying captcha in view and adding scenario condition in controller as below.

In LoginForm model:

public function rules()
{
    return [
        [['username', 'password'], 'required', 'on'=>'loginpage'],
        [['username', 'password'], 'required', 'on'=>'withCaptcha'],
        [['reference_url'], 'safe'],
        [['verifyCode'], 'captcha', 'skipOnEmpty' => true,'on'=>'withCaptcha'],         
        ['username','email', 'on'=>'loginpage', 'message'=> 'Please enter a valid email address'],
        ['password', 'validatePassword', 'on'=>'loginpage'],
        ['password', 'validatePassword', 'on'=>'withCaptcha'],
    ];
}

 public function checkattempts($uname)
{
    $user = \frontend\models\User::findByEmail($uname);
    $ip = $this->get_client_ip();
    if($user){
    $data = (new Query())->select('*')  
                ->from('login_attempts')
                ->where(['ip' => $ip])->andWhere(['user_ref_id' => $user->id])
                ->one();
    if($data["attempts"] >=3){
        return true;
    }else{
        return false;
    }
    }
    return false;
}

in SiteController.php controller

 public function actionLogin() {
    if (!\Yii::$app->user->isGuest) {
        return $this->redirect(Yii::$app->getUrlManager()->getBaseUrl() . '/../../');
    }
    $model = new \common\models\LoginForm();
    $model->scenario = 'loginpage';
    $captcha = false;
    if(Yii::$app->request->post()){
    $post_variables =Yii::$app->request->post('LoginForm');         
        if ($model->checkattempts($post_variables['username'])) {
            $model->scenario = 'withCaptcha'; 
            $captcha = true;
        }
    }
    if ($model->load(Yii::$app->request->post()) && $model->validate()) {
         $model->login(); print_r($model->getErrors()); exit;
    } else {
        return $this->render('login', [
                    'model' => $model, 'captcha' => $captcha,
                ]);
    }

In my login.php view:

 <?php if($captcha) { ?>
            <?= $form->field($model, 'verifyCode')->widget(Captcha::className(), 
        ['template' => '<div class="captcha_img">{image}</div>'
            . '<a class="refreshcaptcha" href="#">'
            . Html::img('/images/imageName.png',[]).'</a>'
            . 'Verification Code{input}',
        ])->label(FALSE); ?>   
            <?php } ?>

In my controller when I am tring to print model errors at $model->login() function it is giving below error everytime even though the verification code is correct.

Array ( [verifycode] => Array ( [0] => The verification code is incorrect. ) )

Why is it failing every time. Is there any mistake in the code written?

Thanks in advance

rji rji
  • 697
  • 3
  • 17
  • 37
  • I think that your code has some design issues and you're overcomplicated this thing. Why you're counting failures for IP and user instead of just by IP? This is less secure (from one IP attacker can do thousands of tries - he can just switch attacked user after 3 failures) and harder to implement, since you don't know whether you should display captcha before form was filled. – rob006 May 24 '18 at 09:55
  • Google reCAPTCHA is more secure than yii\captcha\Captcha. Try using [this](https://github.com/himiklab/yii2-recaptcha-widget) extension. – camelsWriteInCamelCase May 27 '18 at 11:21
  • Did you solve this problem? – camelsWriteInCamelCase May 30 '18 at 18:27

0 Answers0