Создание и сопровождение сайтов

Блог. Yii. Проблемы с Captcha в Yii

Поиск

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

    Небольшое замечание: в данной статье не рассматриваю банальные вещи - AJAX-валидацию, отсутствие GD - об этом много написано.

    Рассмотрим несколько более сложные причины такого поведения.

    Из-за чего вообще возникают такого рода проблемы? Чтобы понять суть необходимы базовые знания о том, как вообще работают механизмы подобного рода.
Все они базируются на cookie. Где-то это происходит явно (программист явным образом указывает, какие данные записать в cookie), либо неявным образом (через механизм сессий).

    Для начинающих рекомендую ознакомиться с соответствующим материалом (вот, например: http://phpfaq.ru/sessions).

Работа с каптчей в Yii для программиста совершенно прозрачна:

  • есть виджет во view:
    $this->widget('CCaptcha');
  • есть валидатор в model:
    public function rules()    {
        return array(
            array('verifyCode', 'captcha'),
        );
    }
    
  • есть отображение картинки в controller:
    public function actions() {
        return array(
            'captcha' => array(
                'class' => 'CCaptchaAction',
                'backColor' => 0xFFFFFF,
            ),
        );
    }
    (кто не в курсе - такой синтаксис вместо actionCaptcha() вызывает метод run() класса CCaptchaAction, находящегося в /framework/web/widgets/captcha/CCaptchaAction.php)

    Таким образом мест возникновения проблем не так уж и много (в сам framework мы не лезем - считаем, что там все нормально).

    Если каптча не отображается - то видимо виджет каптчи не может обратиться в контроллер и получить код картинки. По умолчанию - это /<текущий модуль>/<текущий контроллер>/captcha. Попробуйте напрямую открыть этот адрес (у меня, например, по следующему адресу http://localhost/re/infopages/main/captcha ).

    Вы должны будете увидеть собственно саму картинку. Если этого не произошло - проблема в контроллере:

    Либо в виджете можно явно указать, откуда пытаться брать картинку следущим образом:

$this->widget('CCaptcha',
    array('captchaAction' => '/site/captcha')
);

     Это решает проблему отображения картинки. Но, если мы решим включить "нормальные url" (для SEO, использовать путь вида /re/infopages/main/index вместо /re/index.php?r=infopages/main/index), то натыкаемся на проблему: на первый взгляд все работает.. Но каптча не проходит валидацию (или, возможны варианты - валидация проходит только после обновления страницы и тому подобная мистика).

    Происходит это по одной просто причине. При попытке отобразить каптчу со страницы /infopages/main/view?id=12 происходит обращение к /site/captcha. Возникает проблема безопасности доступа к cookie - получается, что ставится и читается она из разных "папок" сервера с разным уровнем вложенности. В каких-то браузерах, возможно, ошибки не будет.

    Выходов из этой ситуации прост - объявить в контроллере метод для работы с каптчей (в примере с /infopages/main/view?id=12 каптча должна браться, например, с /infopages/main/captcha).

    Вопросы и комментарии приветствуются.