Yii2 добавить правило на основе условия - PullRequest
0 голосов
/ 13 октября 2018

Я создаю веб-сайт с использованием PHP Yii2 Framework и расширения dektrium \ yii2-user для аутентификации пользователя.

Я хочу попросить пользователя ввести капчу, если число неудачных входов превышает три, ноПо умолчанию расширение не поддерживает это.

Теперь я переопределил расширение пользователя и модель LoginForm и добавил необходимые поля и проверки.Однако я не могу понять, как добавить правило, чтобы сделать капчу обязательной только с четвертой попытки.

Можно ли добавлять правила динамически?Я показал упрощенное представление кода ниже и мои комментарии, где мне нужна помощь.Я напишу функции, просто нужна помощь с закомментированной частью.

<?php

namespace app\models\dektrium\user;


class LoginForm extends \dektrium\user\models\LoginForm
{
    public $captcha;
    public $need_captcha;

    public function rules() {
        $rules = parent::rules();

        //This is how you'd normally add a rule, but this will require it for every login
        //The following rule should be added from the login()
        $rules[] = ['captcha', 'captcha', 'message' => 'Too many attempts. Captcha required.'];
        $rules[] = ['need_captcha', 'boolean'];

        return $rules;
    }

    public function login() {
        $success = false;
        $requireCaptcha = false;

        if ($this->validate() && $this->user) {
            if ($this->user->login_attempts > 3) {
                //add rule here to require captcha

                $requireCaptcha = true;
            }

            $success = !$requireCaptcha && $this->validateCaptcha() && $this->validateLogin();

            if ($success) {
                $this->user->updateAttributes(['last_login_at' => time()]);
            }
        }

        return $success;
    }
}

?>

РЕДАКТИРОВАТЬ:

Если есть «необязательный» параметр, обратный к «обязательному»Этого было бы достаточно.Я могу проверить капчу в своем логине ().

РЕДАКТИРОВАТЬ 2:

Я пытался использовать сценарии следующим образом, но модель не загружает значение капчив действии контроллера, перед выполнением проверки.

<?php

namespace app\models\dektrium\user;


class LoginForm extends \dektrium\user\models\LoginForm
{
    public $captcha;
    public $need_captcha;
    public $login_count;

    public function rules() {
        $rules = parent::rules();

        $rules[] = ['captcha', 'captcha', 'message' => 'Too many attempts. Captcha required.', 'on' => ['required_captcha']];
        $rules[] = ['need_captcha', 'boolean'];
        $rules[] = ['login_count', 'integer'];

        return $rules;
    }

    public function login() {
        $this->user = $this->finder->findUserByUsernameOrEmail(trim($this->login));

        if($this->user && $this->user->login_count > 3) {
            $this->scenario = 'required_captcha';
            $this->need_captcha = true;
        }

        $success = parent::login();

        if ($success) {
            $this->user->login_count = 0;
            $this->user->save();
        } else {
            $this->login_count++;

            if ($this->user) {
                $this->user->login_count++;
                $this->user->save();
            }
        }

        if ($this->login_count > 3) {
            $this->scenario = 'required_captcha';
            $this->need_captcha = true;
        }

        return $success;
    }
}

1 Ответ

0 голосов
/ 13 октября 2018

Итак, вот как я это сделал ...

Я использовал правило, основанное на сценарии, и в действии контроллера я установил сценарий, когда условие, для которого мне нужна капча, было истинным.В действительности, контроллер также имел любое расширение, поэтому мне пришлось выполнить некоторое поддерживаемое сопоставление контроллера и установить сценарий с помощью события.

Мои первые попытки сделать это не увенчались успехом, так как я устанавливал сценарий во время проверкифункция, но, вероятно, должен был установить его до того, где это работает.

<?php

namespace app\models\dektrium\user;


class LoginForm extends \dektrium\user\models\LoginForm
{
    public $captcha;
    public $need_captcha;
    public $login_count;

    public function rules() {
        $rules = parent::rules();

        $rules[] = ['captcha', 'required', 'on' => ['use_captcha']];
        $rules[] = ['captcha', 'captcha', 'on' => ['use_captcha']];
        $rules[] = ['need_captcha', 'boolean'];
        $rules[] = ['login_count', 'integer'];

        return $rules;
    }

    public function login() {
        $success = true;
        $this->user = $this->finder->findUserByUsernameOrEmail(trim($this->login));

        if(!$this->need_captcha && $this->user && $this->user->login_count > 3) {
            $this->need_captcha = true;
            $success = false;
        }

        $success = $success && parent::login();

        if ($success) {
            $this->user->login_count = 0;
            $this->user->save();
        } else {
            $this->login_count++;

            if ($this->user) {
                $this->user->login_count++;
                $this->user->save();
            }

            if ($this->login_count > 2)
                $this->need_captcha = true;
        }

        return $success;
    }
}
...