CCaptchaAction + ajax

Предварительное обсуждение найденных ошибок перед отправкой их авторам фреймворка, а также внесение новых предложений.
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

CCaptchaAction + ajax

Сообщение Ekstazi »

Столкнулся со следующей особенностью капчи. У меня есть форма, которая проверяется по аякс с помощью CActiveForm(EFormModelBehabior). В правилах написано как обычно:

Код: Выделить всё

public function rules()
{
return array(
array('verifyCode','captcha','allowEmpty'=>!extension_loaded('gd'))
);
}
 
Капча проверяется как надо, однако если посмотреть в метод validate CCaptchaAction, то можно заметить, что после несколько проверок других полей по аякс(а это приводит и к проверке verifyCode) капча просто перегенерируется. Как вариант решения проблемы:

Код: Выделить всё

    /**
     * Validates the input to see if it matches the generated code.
     * @param string user input
     * @param boolean whether the comparison should be case-sensitive
     * @return whether the input is valid
     */
    public function validate($input,$caseSensitive)
    {
        $code=$this->getVerifyCode();
        $valid=$caseSensitive?($input===$code):!strcasecmp($input,$code);
// Следующей строчки кода и не хватает
// Эта строчка проверяет что запрос на проверку - аякс, и не нужно перегенерировать капчу.
                if(Yii::app()->request->isAjaxRequest) return $valid;
        $session=Yii::app()->session;
        $session->open();
        $name=$this->getSessionKey().'count';
        $session[$name]=$session[$name]+1;
        if($session[$name]>$this->testLimit && $this->testLimit>0)
            $this->getVerifyCode(true);
        return $valid;
    }
 
Если не понятно, то могу выложить архив с исходниками
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение samdark »

Да, есть такое дело. Вариант решения — при валидации через AJAX попробовать использовать сценарий, исключающий валидацию капчи.
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение Ekstazi »

Ну я просто унаследовался от CCaptchaAction и внес вышеописанные поправки, все работает.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение samdark »

Тут такое дело. Допустим, я спамбот. Я начну слать AJAX-запросы пачками (заголовки подделать не проблема) и подбирать код к единственной картинке, которая не регенерируется.
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение Ekstazi »

И вправду :( Две стороны медали.
Аватара пользователя
BuCeFaL
Сообщения: 447
Зарегистрирован: 2010.03.17, 21:22
Откуда: Kiev
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение BuCeFaL »

сталкивался с таким не однократно. Решил во время ajax запроса отключать валидатор для капчи. Для аякс запроса save просто не выполняеться.

Во время аякс валидации все валидируеться (кроме капчи), а во время не аякс вопроса все валидируеться и сохраняеться (в случай успеха) таким образом сервер не отвечает правильная ли капча или не правильная, это можно узнать при сабмите.
Последний раз редактировалось BuCeFaL 2011.02.24, 17:23, всего редактировалось 1 раз.
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение Ekstazi »

Может добавить атрибут skipOnAjax валидатору captcha ?
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение samdark »

Это сценарием реализуется отлично.
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение Ekstazi »

Можно пример ? Что-то я не особо себе представляю это без костылей.
Аватара пользователя
BuCeFaL
Сообщения: 447
Зарегистрирован: 2010.03.17, 21:22
Откуда: Kiev
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение BuCeFaL »

http://www.yiiframework.com/doc/api/1.1 ... #on-detail
+
http://www.yiiframework.com/doc/api/1.1 ... rio-detail

Код: Выделить всё

// if not ajax
$model->setScenario('ajax');
//...

//model :
//validators
array('captcha', 'captcha', 'on'=>'ajax'),
//...
 
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение Ekstazi »

Ну это и так понятно. Ну вот у меня есть код(использую EFormModelBehavior):

Код: Выделить всё

   if($model->saved())
     $this->redirect(array('index'));
 
И сделать чтоб работало как надо без костылей не выйдет, да и плодить сценарии для подобных ситуаций явно излишество, наличие skipOnAjax могло бы решить проблему, тем более что уже есть в некотором роде похожий атрибут - skipOnError
Аватара пользователя
slavcodev
Сообщения: 3134
Зарегистрирован: 2009.04.02, 21:42
Откуда: Valencia
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение slavcodev »

Ekstazi писал(а):наличие skipOnAjax
Никто не мешает свой валидатор сделать.
Жду Yii 3!
Ekstazi
Сообщения: 1428
Зарегистрирован: 2009.08.20, 22:54
Откуда: Молдова, Бельцы
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение Ekstazi »

Согласен, но я подумал что эта опция может быть полезна и для других валидаторов
mrchaos
Сообщения: 18
Зарегистрирован: 2011.03.31, 17:41

Re: CCaptchaAction + ajax

Сообщение mrchaos »

Я прошу прощения за тупость. Решил подсесть на yii, в данный момент разбираюсь и застопорился на капче. Перечитал всё что мог, не осилил. Подскажите подробней как победить.
Аватара пользователя
samdark
Администратор
Сообщения: 9489
Зарегистрирован: 2009.04.02, 13:46
Откуда: Воронеж
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение samdark »

mrchaos
Сообщения: 18
Зарегистрирован: 2011.03.31, 17:41

Re: CCaptchaAction + ajax

Сообщение mrchaos »

Прочитал. Капча то у меня работает. Проблема у меня с ajax, обновляет он капчу при запросе. Куда что вписать что бы не обновляли ajax запросы при валидации капчу?
Аватара пользователя
greatdane
Сообщения: 408
Зарегистрирован: 2010.10.20, 14:05
Откуда: Электросталь
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение greatdane »

В модели

Код: Выделить всё

public function rules()
    {
        // NOTE: you should only define rules for those attributes that
        // will receive user inputs.
        return array(
            //тут еще другие правила
            array('verifyCode', 'captcha', 'on'=>'insert'),
        );
    } 
В контроллере

Код: Выделить всё

$model=new Model("insert"); 
а в том месте, где аякс-валидация - меняем сценарий:

Код: Выделить всё

protected function performAjaxValidation($model)
    {
        if(isset($_POST['ajax']) && $_POST['ajax']==='form')
        {
            $model->setScenario("ajax");
            echo CActiveForm::validate($model);
            Yii::app()->end();
        }
    } 
При этом способе капча не валидируется аяксом, валидация капчи происходит только при сохранении модели.
mrchaos
Сообщения: 18
Зарегистрирован: 2011.03.31, 17:41

Re: CCaptchaAction + ajax

Сообщение mrchaos »

Сделал немного иначе:

Код: Выделить всё

    public function rules() {
        $rules = array(
//тут ещё какие то правила
        );
        if (isset($_POST['ajax']) && $_POST['ajax']==='registration-form') 
            return CMap::mergeArray(parent::rules(),$rules);
        else 
            array_push($rules,array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()));
        return CMap::mergeArray(parent::rules(),$rules);
    }
 
Возможно не всё идеально, опыта поднаберусь проще будет думаться как лучше сделать.
Аватара пользователя
BuCeFaL
Сообщения: 447
Зарегистрирован: 2010.03.17, 21:22
Откуда: Kiev
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение BuCeFaL »

Все намного проще и уже решалось в этой теме (и других). Достаточно исключить из сценариявалидации проверку капчи, а при отправке формы включить. Сделать это можно при помощи scenario.
http://www.yiiframework.com/doc/api/1.1 ... rio-detail
Мы можем задать сценарий через свойство scenario и, с его помощью, задать, какой набор правил использовать для проверки.
http://www.yiiframework.ru/doc/guide/ru/form.model
Аватара пользователя
BuCeFaL
Сообщения: 447
Зарегистрирован: 2010.03.17, 21:22
Откуда: Kiev
Контактная информация:

Re: CCaptchaAction + ajax

Сообщение BuCeFaL »

mrchaos писал(а):Сделал немного иначе:

Код: Выделить всё

    public function rules() {
        $rules = array(
//тут ещё какие то правила
        );
        if (isset($_POST['ajax']) && $_POST['ajax']==='registration-form') 
            return CMap::mergeArray(parent::rules(),$rules);
        else 
            array_push($rules,array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements()));
        return CMap::mergeArray(parent::rules(),$rules);
    }
 
Возможно не всё идеально, опыта поднаберусь проще будет думаться как лучше сделать.
Получение параметров это дело контроллера, насколько я понимаю MVC, модель же работает над данными, а тут она и и получает и обрабатывает. Так же модель жестко привязана к 1 форме (id) .
Ответить