MODX - Добавление reCaptcha в FormIt и Login

Александр Мальцев
Александр Мальцев
24K
33
Содержание:
  1. Получение публичного и секретного ключа reCaptcha
  2. Установка ReCaptchaV2
  3. Настройка ReCaptchaV2
  4. Использование reCaptcha в FormIt
  5. Применение reCaptcha в связке FormIt + AjaxForm
  6. Внедрение reCaptcha в Login
  7. Комментарии

Статья, в которой рассмотрим как на сайт, работающий под управлением MODX Revolution, интегрировать Google reCaptcha. Разбирать reCaptcha будем на базе компонента MODX ReCaptchaV2, который интегрируем в форму обратной связи (FormIt) и на страницу регистрации (Login).

Получение публичного и секретного ключа reCaptcha

Подключения сервиса Google для защиты формы от спама начинается с получения 2 ключей на странице google.com/recaptcha/admin. Один из ключей называется site_key (публичный ключ), а другой secret_key (секретный ключ). Получение ключей является достаточно простой процедурой. Для этого необходимо в представленной на странице форме ввести имя сайта, домена и нажать на кнопку "Регистрация".

Google reCaptcha - Публичный и секретный ключи

Но если вы не зарегистрированы в Google, то дополнительно необходимо будет ещё пройти процедуру регистрации.

Установка ReCaptchaV2

Дополнение ReCaptchaV2 предназначено для интеграции 2 версии сервиса защиты от спама Google reCaptcha в MODX Revolution в виде hook (хука) для сниппетов FormIt и Login.

Установка компонента ReCaptchaV2 в осуществляется на странице "Управление пакетами" (в MODX 2.5: Приложение -> Установщик -> кнопка "Загрузить дополнения). В поле "Поиск" набираем название компонента и нажимаем на кнопку "Загрузить".

После этого возвращаемся к управлению пакетами и нажимаем кнопку "Установить".

MODX - Установка дополнения ReCaptchaV2

Настройка ReCaptchaV2

Процедура настройки дополнения ReCaptchaV2 осуществляется путём ввода ключей в параметры recaptchav2.secret_key и recaptchav2.site_key. Для этого открываем страницу "Системные настройки & События" (в админке MODX: значок "Шестерёнка" -> Системные настройки), фильтруем настройки по recaptchav2 и вводим полученные ключи (site_key, secret_key) в качестве значения соответствующих параметров.

MODX - Настройка компонента ReCaptchaV2

MODX - Ввод ключей в параметры компонента ReCaptchaV2

Использование reCaptcha в FormIt

Внедрение сервиса Google reCaptcha на сайт для защиты формы обратной связи, работающей посредством компонента MODX FormIt, осуществляется путём выполнения 2 действий. Первое что необходимо сделать - это добавить значение recaptchav2 в параметр hooks сниппета FormIt.

Немного информации о том, как работают хуки. Hooks (хуки) в FormIt - это скрипты, которые выполняются последовательно один за другим. Переход к выполнению следующего хука осуществляется только после того как предыдущий вернул true. Это означает следующее: что если какой то из хуков не вернул значение true, то выполнение других хуков, следующих за ним, не выполняется. Поэтому указывать хук recaptchav2 всегда следует до выполнения других действий, например, до отправки формы на почту. В этом случае отправка формы на почту не будет происходить до тех пор, пока хук recaptcha не вернёт значение true.

Например, вызов сниппета FormIt с хуком recaptchav2:

[[!FormIt?
  &hooks=`recaptchav2,email,FormItSaveForm`
  &emailTpl=`MyEmailChunk`
  &emailTo=`user@mail.com`
  &validate=`name:minLength=^2^,
             email:email:required,
             message:minLength=^10^,
             g-recaptcha-response:required`
]]

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

<div class="form-item">
  [[!recaptchav2_render]]
  [[!+fi.error.recaptchav2_error]]
</div>

Например, полный код HTML формы с капчей от Google:

<h2>Контактная форма</h2>
 
[[!+fi.validation_error_message:notempty=`<p>[[!+fi.validation_error_message]]</p>`]]
 
<form action="[[~[[*id]]]]" method="post" class="form">
  <label for="name">
    Имя:
    <span class="error">[[!+fi.error.name]]</span>
  </label>
  <input type="text" name="name" id="name" value="[[!+fi.name]]" />
 
  <label for="email">
    Email:
    <span class="error">[[!+fi.error.email]]</span>
  </label>
  <input type="text" name="email" id="email" value="[[!+fi.email]]" />
 
  <label for="message">
    Сообщение:
    <span class="error">[[!+fi.error.message]]</span>
  </label>
  <textarea name="message" id="message" rows="5" value="[[!+fi.message]]">[[!+fi.message]]</textarea>
 
  <div class="form-item">
    [[!recaptchav2_render]]
    [[!+fi.error.recaptchav2_error]]
  </div>

  <div class="form-buttons">
    <input type="submit" value="Отправить">
  </div>
</form>

Применение reCaptcha в связке FormIt + AjaxForm

Внедрения reCaptcha в форму обратной связи, построенной на основе компонентов FormIt и AjaxForm, осуществляется посредством выполнения 3 шагов.

MODX - Форма обратной связи с Google reCaptcha

1. Добавить в вызов сниппета AjaxForm в параметр hooks значение "recaptchav2" и в параметр validate значение "g-recaptcha-response:required":

[[!AjaxForm? 
  &form=`tpl.AjaxForm` 
  &snippet=`FormIt` 
  &hooks=`recaptchav2,email,FormItSaveForm`
  &emailSubject=`Тестовое сообщение`
  &emailTo=`myemail@mail.ru`
  &emailFrom=`no-reply@mysite.ru`
  &emailTpl=`tpl.email`
  &validate=`name:minLength=^2^,
             email:email:required,
             message:minLength=^10^,
             g-recaptcha-response:required`
  &validationErrorMessage=`В форме содержатся ошибки!`
  &successMessage=`Сообщение успешно отправлено`
]]  

2. Вставить внутрь HTML формы следующий код разметки (отвечает за отображения пользователю reCaptcha и ошибок, связанных с ним):

<div class="form-item">
  [[!recaptchav2_render]]
  [[!+fi.error.recaptchav2_error]]
  <span class="error_g-recaptcha-response error"></span>
</div>

Например, итоговый код чанка tpl.AjaxForm, содержащий HTML форму, которая состоит из 3 полей и гугловской reCaptcha:

<form action="" method="post" id="feedback" class="ajax_form af_example form-horizontal">

  <div class="control-group">
    <label class="control-label" for="af_name">[[%af_label_name]]</label>
    <div class="controls">
      <input type="text" id="af_name" name="name" value="[[+fi.name]]" placeholder="">
      <span class="error_name">[[+fi.error.name]]</span>
    </div>
  </div>

  <div class="control-group">
    <label class="control-label" for="af_email">[[%af_label_email]]</label>
    <div class="controls">
      <input type="email" id="af_email" name="email" value="[[+fi.email]]" placeholder="">
      <span class="error_email">[[+fi.error.email]]</span>
    </div>
  </div>

  <div class="control-group">
    <label class="control-label" for="af_message">[[%af_label_message]]</label>
    <div class="controls">
      <textarea id="af_message" name="message" rows="5">[[+fi.message]]</textarea>
      <span class="error_message">[[+fi.error.message]]</span>
    </div>
  </div>

  <div class="form-item">
    [[!recaptchav2_render]]
    [[!+fi.error.recaptchav2_error]]
    <span class="error_g-recaptcha-response error"></span>
  </div>

  <div class="control-group">
    <div class="controls">
      <button type="reset" class="btn btn-default">[[%af_reset]]</button>
      <button type="submit" class="btn btn-primary">[[%af_submit]]</button>
    </div>
  </div>
  
  [[+fi.success:is=`1`:then=`
    <div class="alert alert-success">[[+fi.successMessage]]</div>
  `]]
  [[+fi.validation_error:is=`1`:then=`
    <div class="alert alert-danger">[[+fi.validation_error_message]]</div>
  `]]
</form>

3. Добавление скрипта js на страницу, который будет выполнять сброс сессии капчи после получения ответа с сервера (в новых версиях компонента AjaxForm этот шаг выполнять не надо).

В зависимости от предпочтений веб-разработчика js-скрипт можно подключить к странице различными способами. Рассмотрим основные из них.

1 вариант - с помощью элемента script.

// после загрузки страницы
$(function(){
  // добавляем обработчик на событие, которое возникает при получении ответа от сервера
  $(document).on('af_complete', function(event, response) {
    // получаем отправленную форму
    var form = response.form;
    // проверяем id формы
    if (form.attr('id') == 'feedback') {
      // перезагружаем recaptcha
      grecaptcha.reset();
    }
  });
});

2 вариант - посредством размещения вышеприведённого javascript кода в своём файле js.

3 вариант - помещение вышепредставленного кода в файл js, используемом сниппетом AjaxForm по умолчанию assets/components/ajaxform/js/default.js.

// найти в файле default.js ajaxform следующие строки
AjaxForm.Message.success(response.message);
form.find('.error').removeClass('error');
form[0].reset();
// и вставить после них следующее
if (typeof $('#recaptcha') != "undefined") {
  grecaptcha.reset(); //добавляем сброс сессии для капчи
}

Но лучше не изменять оригинальный файл, а сделать его копию (например, default2.js) и произвести изменения уже в ней. После этого указать в параметре сниппета путь к этому файлу посредством параметра frontend_js.

[[!AjaxForm? 
  ...
  &frontend_js=`путь/до/default2.js
  ...
]]

Узнать, как работать с дополнениями FormIt и AjaxForm можно в статье "MODX - Форма обратной связи".

Внедрение reCaptcha в Login

Дополнение reCpatchaV2 также можно использовать в сниппетах компонента Login. Например, защитим от спама с помощью reCapctha 2 форму регистрацию, работающую под управлением сниппета Register.

MODX - Форма регистрации с Google reCaptcha

Для этого необходимо:

1. Добавить в вызов сниппета Register параметр preHooks со значением recaptchav2:

[[!Register?
  ...
  &placeholderPrefix=`reg.`
  &preHooks=`recaptchav2`
]]

2. В HTML форму код для вывода изображения Google reCaptcha:

<div class="form-item">
  [[!recaptchav2_render]]
  [[!+reg.error.recaptchav2_error:notempty=`Пожалуйста, отметьте флажок на reCaptcha`]]
</div>

Информацию по использованию компонента Login можно найти на странице "Создание системы регистрации пользователей на сайте, работающим под управлением MODX Revolution".

Комментарии:

  1. Сергій
    26 февраля 2021, 00:37
    Шеф. А вы не знаете как подключить до Login двухфакторную аутентификацию?
    Вот это было бы классно.
    1. Maxim Sokolkov
      24 августа 2020, 10:52
      Здравствуйте. Сделал всё по инструкции, но капча не выводится на странице, а в логах ошибка:
      /public_html/core/model/modx/modparser.class.php : 541) Could not find snippet with name recaptchav2_render.
      С чем это может быть связано и как это исправить?
      1. Александр Мальцев
        24 августа 2020, 12:19
        Здравствуйте! Дополнение «ReCaptchaV2» установили в MODX? Публичный и секретный ключ reCaptcha задали в настройках?
      2. DrMcSheen
        08 ноября 2018, 12:03
        А как встроить капчу в отправку комментариев? Так не работает
        [[!TicketComments?
            &allowGuest=`1`
            &allowGuestEdit=`0`
            &autoPublish=`0`
            &autoPublishGuest=`0`
            &enableCaptcha=`1`
            &formBefore=`1`
            &depth=`1`
            &preHooks=`recaptchav2`
            &validate=`g-recaptcha-response:required`
        ]]
        1. Александр Мальцев
          08 ноября 2018, 14:30
          Компонент ReCaptchaV2 работает только в связке с компонентами Login и FormIt. Он не предназначен для Tickets.
          Чтобы использовать для защиты комментариев от спама Google reCAPTCHA необходимо доработать сам компонент Tickets, а именно добавить в него такую возможность.
        2. Сергей
          24 августа 2018, 11:14
          Добрый день!
          Почему-то только на одном из сайтов надпись «Я не робот» на английском, не подскажите, как на русский изменить?
          Пробовал переустанавливать recaptchav2 и пересоздавал ключи на google.com/recaptcha/admin.
          1. Александр Мальцев
            24 августа 2018, 12:50
            Добрый! Это определяется параметром cultureKey.
            Данный параметр используется для того, чтобы MODX мог правильно понимать язык сайта и подгружать соответствующие лексиконы. Данный параметр, чтобы использовался русский язык, должен быть установлен, равным ru.
            Кроме этого параметр cultureKey может быть переопределён на уровне контекста сайта. Необходимо проверить его значение там и при необходимости изменить на ru.
            1. Сергей
              24 августа 2018, 12:57
              Помогло! Благодарю за Ваш труд!
          2. Паша
            05 мая 2018, 11:41
            Добрый день, Александр. В логе очень много таких ошибок public_html/core/components/formit/src/FormIt/Request.php: 87) [FormIt] Невозможно загрузить класс reCaptcha. Подскажите что подправить?
            1. Ник
              09 июня 2018, 10:29
              Та же проблема.
              1. Александр Мальцев
                11 июня 2018, 04:48
                Откройте файл Request.php и измените строчку 82 на:
                if ($this->formit->hasHook('recaptcha') && !($this->formit->hasHook('recaptchav2'))) { //if ($this->formit->hasHook('recaptcha')) {
                
                1. Ник
                  11 июня 2018, 13:41
                  Александр, спасибо!
            2. Илья
              11 декабря 2017, 09:32
              Доброго Шеф! Подскажи как можно прикрутить капчу к авторизации Office. Несколько тысяч лишних юзеров появилось.
              1. Александр Мальцев
                11 декабря 2017, 11:27
                Добрый день! Авторизация — это проверка логина и пароля. Если эта проверка проходит, то пользователь получает некоторый набор прав. Если нет, то он их не получает. Это действие не создаёт пользователей.
                1. Илья
                  11 декабря 2017, 12:18
                  Прошу прощения. Нужно воткнуть капчу на регистрацию.

                  1. Александр Мальцев
                    11 декабря 2017, 14:54
                    Для этого необходимо вставить капчу в форму. Как это сделать, можно посмотреть в этой статье.
                    После этого открыть файл /core/components/office/controllers/auth.class.php и добавить в него, а точнее в функцию formRegister следующее:
                    /**
                    * Create new user and confirm his email
                    *
                    * @param $data
                    *
                    * @return array|string
                    */
                    public function formRegister($data) {
                    
                        //...
                    
                        // Check captcha
                        $captcha = trim(@$data['captcha']);
                        if (empty($captcha)) {
                            return $this->error($this->modx->lexicon('office_auth_err_captcha_empty'));
                        } else if ($_SESSION["captcha"] != $captcha) {
                            return $this->error($this->modx->lexicon('office_auth_err_captcha_invalid'));
                        }
                    
                        return $this->_createUser(array(
                            'username' => $username,
                            'email' => $email,
                            'mobilephone' => $mobilephone,
                            'password' => $password,
                            'fullname' => $fullname,
                        )
                    
                    Для вывода ошибок в словаре MODX создать ключи office_auth_err_captcha_empty и office_auth_err_captcha_invalid с необходимыми сообщениями.
                    1. Илья
                      11 декабря 2017, 16:09
                      Шеф спасибо за ответ! а не скажешь как прикрутить гугловскую капчу? Сейчас на сайте стоит ReCaptchaV2.
                      Она очень хорошо вяжется с Formit и AjaxForm. Можно ли как от по образу и подобию совершить это с Office?
                      1. Александр Мальцев
                        11 декабря 2017, 16:22
                        Наверно, так просто не получится. Данное дополнение для этого не спроектировано. Прикручивать рекапчу к форме нужно будет самостоятельно, т.е. не используя этот компонент.
                        1. Илья
                          11 декабря 2017, 16:53
                          Принципе я так и думал. Благодарю за консультацию!
              2. Arhivar
                10 августа 2017, 14:14
                Привет Шеф!
                А подскажите, как сделать две таких Капчи на одной странице?
                1. Александр Мальцев
                  10 августа 2017, 16:22
                  Привет. Для этого необходимо дорабатывать дополнение. Из коробки он это сделать не может.
                  Если очень нужно, то возьму это на заметку.
                  1. Arhivar
                    10 августа 2017, 16:43
                    Нужно! На странице две формы! А капча только одна)
                    Возьмите, на заметку пожалуйста!
                    Спасибо.
                2. Arhivar
                  21 февраля 2017, 11:01
                  Привет Шеф!!!
                  Подскажи пожалуйста, а возможно ли менять размеры и внешний вид этой капчи?
                  А более конкретно задача — сайт на bootstrap и эта капча не влезает полностью на экран телефона…

                  1. Александр Мальцев
                    23 февраля 2017, 16:43
                    Привет! Можно просто отмасштабировать reCaptcha (например, на 0.8). Для этого в CSS можно добавить следующий код:
                    @media screen and (max-width: 575px){ 
                      #rc-imageselect, .g-recaptcha {
                        transform: scale(0.8);
                        -webkit-transform: scale(0.8);
                        transform-origin: 0 0;
                        -webkit-transform-origin: 0 0;
                      }
                    }
                    
                    1. Arhivar
                      24 февраля 2017, 13:57
                      Спасибо, помогло!
                  2. nordrussian
                    21 октября 2016, 01:02
                    Не заработала, бьюсь уже больше месяца, все перепробовал не срабатывает, если не поставить галку я не робот, все равно отправляет письмо.
                    1. Александр Мальцев
                      22 октября 2016, 14:05
                      Проверьте все моменты, может быть вы что-то где-то упустили…
                      1. nordrussian
                        25 октября 2016, 19:03
                        Добрый вечер. Пните меня куда копать?
                        сайт bsambo34.ru

                        Форма.
                        [[!FormIt?
                        &hooks=`recaptchav2,email,redirect`
                        &validate=`contact_name:required,
                        contact_email:email:required,
                        contact_message:required,
                        g-recaptcha-response:required`
                        &emailTpl=`sentEmailTpl`
                        &emailSubject=`Сообщение с сайта "боевое самбо"`
                        &emailTo=`nordrussian@ya.ru`
                        &redirectTo=`19`
                        ]]
                        
                        <form id="contact_name"  action="[[~[[*id]]]]" method="post">
                                                    
                        							<label>Имя: *</label>
                                                    <input type="text" name="contact_name" id="contactName" required="required" size="30"  minlength="2" maxlength="40" value="[[!+fi.contact_name]]" required/>
                                                    
                        							<label>E-mail: *</label>
                                                    <input type="email" name="contact_email" id="contactMail" size="30"  required="required" value="[[!+fi.contact_email]]"  required/>
                        							
                        							<label>Телефон: *</label>
                                                    <input type="text" name="tel" id="tel" required="required" size="30"  minlength="2" maxlength="40" value="[[!+fi.tel]]"  required/>
                        							
                        							<label>Сообщение: *</label>
                                                    <textarea name="contact_message" id="contactMessage" required="required"cols="70" rows="7">[[!+fi.contact_message]]</textarea>
                        
                        
                        
                        <div class="form-item">
                          [[!recaptchav2_render]]
                          [[!+fi.error.recaptchav2_error]]
                        </div>
                        
                        							<input type="submit" id="sendMessage" name="sendMessage" class="button" value="Отправить" />
                                                </form>
                        
                        <img
                        src=«http://itchief.ru/assets/uploadify/1/a/b/1ab010a44d15848a10a1f66246b09e4es.jpg» class=«fancybox thumbnail center»>


                        <img
                        src=«http://itchief.ru/assets/uploadify/3/6/d/36def77fb30dc825208e0984caf75cb9s.jpg» class=«fancybox thumbnail center»>

                        1. Александр Мальцев
                          26 октября 2016, 12:43
                          Не знаю что Вам подсказать… Попробуйте вместо [[~[[*id]]]] указать обычный адрес страницы в которой расположен сниппет FormIt.
                          1. nordrussian
                            26 октября 2016, 13:57
                            В принципе заработало, если поставить галку, то сообщения уходят с сайта и приходят на почту. Если галочку не поставить, то страница просто перезагружается и на почту письмо не уходит, данные внесенные в форму сохраняются, а вот recaptcha предупреждений не выводит о том, что она обязательна для заполнения.
                        2. nordrussian
                          25 октября 2016, 10:15
                          Несколько раз проверял — не работает, вечером попробую код написать.
                      2. Алексей
                        08 сентября 2016, 16:41
                        Будь Здрав, Шеф!
                        А будет урок как прикрепить файл к FormIt и к комментариям как у тебя?)
                        1. Александр Мальцев
                          12 сентября 2016, 13:34
                          Да, будет.
                        Войдите, пожалуйста, в аккаунт, чтобы оставить комментарий.