Ошибка капчи битрикс

Проверяем права на хостинге

Особого внимания заслуживают следующие файлы и папки:

  • /bitrix/tools/
  • /bitrix/tools/captcha.php
  • /bitrix/tmp/
  • /bitrix/modules/main/tools/
  • /bitrix/modules/main/tools/captcha.php

Права на них должны соотвествовать тем, что стоят у вас в данных константах в dbconn.php.

define("BX_FILE_PERMISSIONS", 0644);
define("BX_DIR_PERMISSIONS", 0755);

Но для верности, можно поставить всем 0777 на время эксперимента.

Проверим наличие библиотеки FreeType

Тут, если не знаем как — нужно просто написать в тех. поддержку хостинга или обратится к системному администратору вашего хостинга / сервера.

Проверить наличие пустых строк в init.php

Иногда, это ломает капчу. Сделайте бекап файла и очистите его содержимое, залейте на сервер по FTP. Если после обновления страницы капча появилась, то удалите все пустые строчки(лишние табы, пробелы в первой строке) из файла и залейте его обратно.

Заметки разработчика: Битрикс не выводит капчу

23 апреля 2020

Просмотры
7744

Столкнулись с интересной проблемой на одном из клиентских сайтов. Не отображается изображение контрольного слова для проверки (captcha).

Многие владельцы сайтов на 1С-Битрикс не раз видели при входе в административный раздел сайта, в форме авторизации предложение «Введите слово на картинке».

Этот же механизм используется и в публичной части сайта при регистрации пользователей, авторизации. Но он как и всё остальное, может работать не корректно.

Сегодня столкнулись с проблемой, когда на сайте клиента картинка с кодовым словом просто не отображается. Ситуация решилась достаточно быстро, суть проблемы заключалась в лишнем выводе символов в файле /bitrix/php_interface/dbconn.php. В конце файла был просто символ пробела. Такая же проблема может возникнуть и файле /bitrix/php_interface/init.php. Эти файлы не должны выводить каких либо символов, строго php код.

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

Надеемся, что помогли Вам!

После обновления версии PHP с 7.4 на 8.1 Битрикс ругается и выдает ошибку

[TypeError] 
call_user_func_array(): Argument #1 ($callback) must be a valid callback, non-static method B01110011ReCaptchaBitrixCaptcha::initCheckSpam() cannot be called statically (0)

Пробовал добавлять static к function но не помогает. Код класса:

class BitrixCaptcha
{
    /**
     * Подключаем JS скрипты для reCaptcha v3
     */
    public function initJS()
    {
        $Asset = Asset::getInstance();
        $siteKey = Option::get(M::id(), 'site_key_'. SITE_ID);
        $hideBadge = Option::get(M::id(), 'hide_badge_'. SITE_ID, 'Y');

        if (empty($siteKey)) return true;

        $Asset->addString('<script src="https://www.google.com/recaptcha/api.js?render='. $siteKey .'"></script>');
        $Asset->addString('<script>window.recaptcha = { siteKey: "'. $siteKey .'", tokenLifeTime: 100 };</script>'); // время жизни токена в секундах (2 минуты максимальное время жизни токена)
        $Asset->addString('<script src="/bitrix/js/b01110011.recaptcha/script.js"></script>');
        
        if ($hideBadge == 'Y')
            $Asset->addString('<style>.grecaptcha-badge {display: none;}</style>');
    }

    /**
     * Подключаем проверку на спам
     */
    public function initCheckSpam()
    {
        $secretKey = Option::get(M::id(), 'secret_key_'. SITE_ID);
        if (empty($secretKey)) return true;

        $EventManager = EventManager::getInstance();

        $EventManager->addEventHandler('form', 'onBeforeResultAdd', ['B01110011ReCaptchaBitrixCaptcha', 'checkWebForm']);
        $EventManager->addEventHandler('main', 'OnBeforeUserRegister', ['B01110011ReCaptchaBitrixCaptcha', 'checkRegistration']);
        $EventManager->addEventHandler('main', 'OnBeforeEventAdd', ['B01110011ReCaptchaBitrixCaptcha', 'checkFeedback']);
        $EventManager->addEventHandler('iblock', 'OnBeforeIBlockElementAdd', ['B01110011ReCaptchaBitrixCaptcha', 'checkIBlock']);
        $EventManager->addEventHandler('sale', 'OnBeforeOrderAdd', ['B01110011ReCaptchaBitrixCaptcha', 'checkSaleOrder']);
    }

    /**
     * Проверка форм из модуля веб форм
     */
    public function checkWebForm($WEB_FORM_ID, &$arFields, &$arValues)
    {
        if ($arFields['RECAPTCHA_DISABLE']) return true;

        $webformIDs = Option::get(M::id(), 'webform_ids_'. SITE_ID);
        if (empty($webformIDs)) return true;

        // если не из списка проверяемых форм пришли данные, то не проверяем капчу
        $webformIDs = explode(',', $webformIDs);
        if (!in_array($WEB_FORM_ID, $webformIDs, true)) return true;
        
        return self::checkSpam();
    }

    /**
     * Проверка при регистрации пользователя
     */
    public function checkRegistration(&$arArgs)
    {
        $registrationEnable = Option::get(M::id(), 'registration_enable_'. SITE_ID, 'N');
        if ($registrationEnable == 'N') return true;

        return self::checkSpam();
    }

    /**
     * Проверка при оформлении заказа
     */
    public function checkSaleOrder(&$arFields)
    {
        if ($arFields['RECAPTCHA_DISABLE']) return true;

        $saleOrderEnable = Option::get(M::id(), 'sale_order_enable_'. SITE_ID, 'N');
        if ($saleOrderEnable == 'N') return true;

        return self::checkSpam();
    }

    /**
     * Проверка при отправки формы обратной связи main.feedback
     */
    public function checkFeedback(&$event, &$lid, &$arFields, &$messageId, &$files, &$languageId)
    {
        if ($arFields['RECAPTCHA_DISABLE']) return true;

        $feedbackIDs = Option::get(M::id(), 'main_feedback_ids_'. SITE_ID);
        if (empty($feedbackIDs)) return true;

        // если не из списка проверяемых форм пришли данные, то не проверяем капчу
        $feedbackIDs = explode(',', $feedbackIDs);
        if (!in_array((string) $messageId, $feedbackIDs, true)) return true;
        
        return self::checkSpam();
    }

    /**
     * Проверка при добавлении в инфоблок
     */
    public function checkIBlock(&$arParams)
    {
        if ($arParams['RECAPTCHA_DISABLE']) return true;

        $iblockIDs = Option::get(M::id(), 'iblock_ids_'. SITE_ID);
        if (empty($iblockIDs)) return true;

        // если не из списка проверяемых инфоблоков пришли данные, то не проверяем капчу
        $iblockIDs = explode(',', $iblockIDs);
        if (!in_array((string) $arParams['IBLOCK_ID'], $iblockIDs, true)) return true;
        
        return self::checkSpam();
    }

    /**
     * Основной метод проверки капчи
     */
    public function checkSpam()
    {
        global $APPLICATION;

        // если мы добавляем данные из админки, то не проверяем
        if (preg_match('/^/bitrix/admin/.*$/i', $APPLICATION->GetCurPage())) return true;

        $isError = false;
        $recaptcha_token = $_REQUEST['recaptcha_token'];

        if (isset($recaptcha_token) && !empty($recaptcha_token))
        {
            $secretKey = Option::get(M::id(), 'secret_key_'. SITE_ID);
            $permissibleScore = (float) Option::get(M::id(), 'permissible_score_'. SITE_ID, 0.5);

            $recaptcha = new ReCaptcha($secretKey, $permissibleScore);
            $response = $recaptcha->verify($recaptcha_token);

            if (!$response['isSuccess']) $isError = true;
        }
        else
        {
            $isError = true;
        }

        if ($isError)
        {
            $errorMessage = Option::get(M::id(), 'error_message_'. SITE_ID);
            if (empty($errorMessage)) $errorMessage = Loc::getMessage(M::locPrefix() .'CAPTCHA_ERROR_MESSAGE');

            $APPLICATION->ThrowException($errorMessage);
            return false;
        }
    }
}

Помогите пожалуйста исправить проблему.

капча подключается в файле с формой

include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/captcha.php");
$cpt = new CCaptcha();
$captchaPass = COption::GetOptionString("main", "captcha_password", "");
if(strlen($captchaPass) <= 0)
	{
	    $captchaPass = randString(10);
	    COption::SetOptionString("main", "captcha_password", $captchaPass);
	}
$cpt->SetCodeCrypt($captchaPass);

Есть некая форма с капчей. без использования аякса

....
<form  action="/reviews/finish.php" enctype="multipart/form-data" accept-charset="UTF-8">
				<!--captcha_code-->
				<input name="captcha_code" value="<?=htmlspecialchars($cpt->GetCodeCrypt());?>" type="hidden">
				<input id="captcha_word" name="captcha_word" type="text">
				<img src="/bitrix/tools/captcha.php?captcha_code=<?=htmlspecialchars($cpt->GetCodeCrypt());?>">
</form>
....

обработчик формы в другом файле. В нем есть проверка капчи

if(!$APPLICATION->CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_code"]))
	{
	    // Неправильное значение
	}
	else
	{
	    // Правильное значение
дальнейший код работы с формой
}

при отправке формы уходят captcha_code и captcha_word , но обработчик выдает ошибку. Что делаю не так?

Представляю Вашему вниманию короткую статью о том, как искать объяснение непонятных явлений в битриксе. В качестве примера приведу историю — когда-то, еще на заре изучения системы, мне удалось вывести в форме авторизации капчу. Причем как это вышло, выяснить не получилось. И вот сейчас, кастомизируя очередной шаблон компонента авторизации, обнаружился код ее выводящий. Спортивный интерес и отсутствие информации в официальной документации (хотя вполне может быть, я просто не нашел то что нужно) подтолкнули меня на маленькое расследование.

Первым делом, надо посмотреть в шаблоне компонента элемент массива, в котором приходит флаг показа капчи — несложно увидеть, что это $arResult[«CAPTCHA_CODE»]. Массив arResult формируется внутри компонента, поэтому следующим шагом стало изучение содержимого bitrixcomponentsbitrixsystem.auth.formcomponent.php. Найденный фрагмент кода показал, что за капчу отвечает функция NeedCAPTHAForLogin, которая по логину пользователя решает, выводить ее или нет.

if($APPLICATION->NeedCAPTHAForLogin($arResult["USER_LOGIN"]))
{
    $arResult["CAPTCHA_CODE"] = $APPLICATION->CaptchaGetCode();
}
else
{
    $arResult["CAPTCHA_CODE"] = false;
}

Api-help битрикса о назначении NeedCAPTHAForLogin рассказывать отказался, в настройках пользователя заветной галочки не оказалось. Остается найти и посмотреть исходник этой загадочной функции. С помощью Total Commander (или аналога) в директории bitrixmodulesmain ищем файлы, содержащие текст NeedCAPTHAForLogin. Напомню, что такие исследования доступны счастливым обладателям версии в исходных кодах. Итак, результат поиска — файлик bitrixmodulesmainclassesgeneralmain.php. Находим кусок кода функции NeedCAPTHAForLogin, который ставит все точки над i

if(strlen($login) > 0)
{
    $rsUser = CUser::GetList($o, $b, array("LOGIN_EQUAL_EXACT" => $login));
    $arUser = $rsUser->Fetch();
    if($arUser)
    {
        $arPolicy = CUser::GetGroupPolicy($arUser["ID"]);
        $POLICY_ATTEMPTS = intval($arPolicy["LOGIN_ATTEMPTS"]);
        $USER_ATTEMPTS = intval($arUser["LOGIN_ATTEMPTS"]);
    }
}

Оказывается, вывод капчи в форме авторизации регулируется в настройках групповой политики неприметной галочкой в самом конце списка.

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

Не проходит капча

06.08.2014, 11:36. Показов 5562. Ответов 3


Студворк — интернет-сервис помощи студентам

Привет всем, возникла такая необходимость, добавить капчу на форму добавления отзывов.
Есть шаблон с детальным описанием товара, в нем 2 формы, одна подключается как компонент битрикс (bitrix:form.result.new), в админке у неё стоит галочка использовать капчу и она работает, а вот вторая реализована как html

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/captcha.php");
$cpt = new CCaptcha();
/*$captchaPass = COption::GetOptionString("main", "captcha_password", "");
if(strlen($captchaPass) <= 0)
{
    $captchaPass = randString(10);
    COption::SetOptionString("main", "captcha_password", $captchaPass);
}*/
//$cpt->SetCodeCrypt($captchaPass);
$cpt->SetCode();
?>
 
<form name="REPLIE<?=$arParams["form_index"]?>"  action="<?=POST_FORM_ACTION_URI?>#postform"<?
    ?> method="POST" enctype="multipart/form-data" id="REPLIER<?=$arParams["form_index"]?>" onsubmit="return ValidateForm(this, '<?=$arParams["AJAX_TYPE"]?>', '<?=$arParams["AJAX_POST"]?>', '<?=$arParams["PREORDER"]?>', $('#captcha_word').val(), $('#captcha_code').val());">
    <input type="hidden" name="back_page" value="<?=$arResult["CURRENT_PAGE"]?>" />
    <input type="hidden" name="ELEMENT_ID" value="<?=$arParams["ELEMENT_ID"]?>" />
    <input type="hidden" name="SECTION_ID" value="<?=$arResult["ELEMENT_REAL"]["IBLOCK_SECTION_ID"]?>" />
    <input type="hidden" name="save_product_review" value="Y" />
    <input type="hidden" name="preview_comment" value="N" />
    <?=bitrix_sessid_post()?>
<?
if ($arParams['AUTOSAVE'])
    $arParams['AUTOSAVE']->Init();
?>
    <div class="order_block">
<?
/* GUEST PANEL */
if (!$arResult["IS_AUTHORIZED"]) {?>
<div class="order_block_left review-block">
  <div class="input_row">
    <input name="REVIEW_AUTHOR" id="REVIEW_AUTHOR<?=$arParams["form_index"]?>" size="30" type="text" value="<?=$arResult["REVIEW_AUTHOR"] == "Гость" ? "" : $arResult["REVIEW_AUTHOR"]?>" tabindex="<?=$tabIndex++;?>" placeholder="<?=GetMessage("OPINIONS_NAME")?> *"/>
  </div>
  <div class="input_row">
    <input type="text" name="REVIEW_EMAIL" id="REVIEW_EMAIL<?=$arParams["form_index"]?>" size="30" value="<?=$arResult["REVIEW_EMAIL"]?>" tabindex="<?=$tabIndex++;?>" placeholder="<?=GetMessage("OPINIONS_EMAIL")?> *"/>
  </div>
  <span class="must_fill_text">* - поля обязательные для заполнения</span>
</div>
<?}?>
  <div class="order_block_right">
    <div class="input_row">
      <textarea name="REVIEW_TEXT" cols="30" rows="10" placeholder="<?=$arParams["MESSAGE_TITLE"]?> *"><?=isset($arResult["REVIEW_TEXT"]) ? $arResult["REVIEW_TEXT"] : ""?></textarea>
    </div>
  <div class="form_submit">
    <?//$captcha_code = htmlspecialchars($cpt->GetSID());?>
    <input type="hidden" name="captcha_sid" value="<?=$cpt->GetSID()?>" id="captcha_code" />
    <span style="color:rgb(246, 246, 246);">Введите код с картинки:</span>
    <img src="/bitrix/tools/captcha.php?captcha_sid=<?=$cpt->sid?>" width="133" height="29" alt="CAPTCHA" id="img_capcha" />
    <input type="text" name="captcha_word" style="margin-bottom: 10px;" id='captcha_word'/>
 
    <input class="button order_btn" name="send_button" type="submit" value="<?=GetMessage("OPINIONS_SEND")?>" tabindex="<? echo isset($tabIndex) ? $tabIndex++ : 0;?>" /> <!--onclick="this.form.preview_comment.value = 'N';"-->
  </div>
</div>
 
 
    </div>
</form>

Проверка валидности в этой форме отдано на откуп js onsubmit=»return ValidateForm(this, ‘<?=$arParams[«AJAX_TYPE»]?>’, ‘<?=$arParams[«AJAX_POST»]?>’, ‘<?=$arParams[«PREORDER»]?>’, $(‘#captcha_word’).val(), $(‘#captcha_code’).val());»
Делал это не я, поэтому нарушать текущий порядок не хочется, поэтому добавил в эту функцию ajax запрос

Javascript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$.ajax(
 {
  url: "/captcha.php",
  type: "POST",
  dataType: "html",
  async:false,
  data: { captcha_word: captcha_word, captcha_sid: captcha_sid},
  success: function(data)
    {
      result = data.substr(data.search("response")+10,1)
      console.log(data);
      if(result == 'N')
      {
        errors += "Введены не верные символы с картинкиn";
        //alert(errors);
      }
    },
  });

в результате должно возвращаться либо Y либо N.
Вот код captcha.php

PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php
include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/header.php");
 
include_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/classes/general/captcha.php");
 
$cpt = new CCaptcha();
print_r($_POST);
var_dump($cpt->CheckCaptchaCode($_POST["captcha_word"],$_POST["captcha_code"]));
var_dump($APPLICATION->CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_code"]));
print_r($_SESSION);
echo "<div id='response'>";
//if($cpt->CheckCaptchaCode(trim($_POST["captcha_word"]), trim($_POST["captcha_code"])))
if($APPLICATION->CaptchaCheckCode($_POST["captcha_word"], $_POST["captcha_code"]))
{
 echo 'Y';
}
else
{
  echo 'N';
}
?>
</div>

И вот проблема, всегда возвращается N, даже при правильном вводе символов с картинки.

HTML5
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
Array
(
    [captcha_word] => F9PEN
    [captcha_sid] => 0ee3e6570f8a8668a32e644328013748
)
bool(false)
bool(false)
Array
(
    [SESS_AUTH] => Array
        (
            [POLICY] => Array
                (
                    [SESSION_TIMEOUT] => 180
                    [SESSION_IP_MASK] => 0.0.0.0
                    [MAX_STORE_NUM] => 10
                    [STORE_IP_MASK] => 0.0.0.0
                    [STORE_TIMEOUT] => 525600
                    [CHECKWORD_TIMEOUT] => 525600
                    [PASSWORD_LENGTH] => 6
                    [PASSWORD_UPPERCASE] => N
                    [PASSWORD_LOWERCASE] => N
                    [PASSWORD_DIGITS] => N
                    [PASSWORD_PUNCTUATION] => N
                    [LOGIN_ATTEMPTS] => 0
                    [PASSWORD_REQUIREMENTS] => Пароль должен быть не менее 6 символов длиной.
                )
 
        )
 
    [SESS_IP] => 127.0.0.1
    [SESS_TIME] => 1407309158
    [BX_SESSION_SIGN] => ba25f2812200d57383385747eae5f3dd
    [SESS_OPERATIONS] => Array
        (
        )
 
    [fixed_session_id] => b73b2c93973fd26ccbb9c763c98985dd
    [BX_SESSION_COUNTER] => 5
    [BX_SESSION_TERMINATE_TIME] => 1407319958
    [SESS_INCLUDE_AREAS] => 
    [IBLOCK_COUNTER] => Array
        (
            [0] => 745
        )
 
    [FORUM] => Array
        (
            [GUEST] => Array
                (
                    [0] => 1407309102
                )
 
            [GUEST_TID] => Array
                (
                    [13] => 1407309102
                )
 
            [LAST_VISIT_FORUM_0] => 1407309102
        )
 
)
<div id='response'>N</div>



0



  • Что такое капча и какие с ней бывают проблемы
  • Google-капча: принцип работы
  • Как подключить reCAPTHCA в Битрикс
    • Решения из MarketPlace
    • Как сделать самим
  • Выводы

Что такое капча и какие с ней бывают проблемы

Что такое “капча” сегодня знает даже школьник. А вот “зачем” — хорошо знают владельцы сайтов.

Любая капча это палка о двух концах. Сложная капча хорошо защищает от спам-роботов, но она же мешает клиентам отправить заявку или заказ. Простая — наоборот, удобна для людей и уязвима для роботов. Пример капчи
На помощь, с девизом “Просто для людей, сложно для роботов”, спешит Google reCapthca.

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

Google-капча: принцип работы

reCAPTCHA представляет из себя небольшой виджет. Для большинства пользователей он выглядит как просто поле с галочкой. Галочка reCAPTCHA
В некоторых случаях потребуется пройти небольшое задание, чтобы доказать что Вы не робот. Например, Google может попросить Вас выбрать из списка изображения с определенным объектом, или выделить на одном изображении нужный объект: Выбор картинок в reCAPTCHA
Потребуют ли от Вас проходить такое задание или нет зависит от того, что Google знает о Вас.

Если Ваши действия в интернете похожи на человеческие (вы читаете разные сайты, авторизованы в почте, вводите поисковые запросы) — скорее всего проходить квест не потребуется.

Работа большинства капч основана на задаче распознавания текста. Роботы плюс-минус научились их разгадывать. Google reCaptcha 2.0 пошла дальше и использует задачи распознавания изображений. Пока роботы угадывают изображения сильно хуже людей.

Как подключить reCAPTHCA в Битрикс

Мы бы хотели найти такую волшебную таблетку, которая решит эту задачу. Но наше исследование показывает что пока ее нет. Поэтому кроме обзора MarketPlace-решений мы опишем наше видение архитектурно-правильных вариантов такой интеграции.

Решения из MarketPlace

Маркетплейс предлагает несколько решений для подключения рекапчи. Среди них есть платные и бесплатные. Все обещают примерно одинаковую функциональность: включение и отключение рекапчи на всем сайте буквально в один клик. Нужно только зарегистрировать Ваш домен на сайте www.google.com/recaptcha и вписать 2 полученных ключа в настройках модуля.

Наиболее больные острые вопросы при подключении рекапчи:

  • поддержка нескольких капч на странице;
  • капча во всплывающем окне, которое потенциально загружается по AJAX.

Как же справляются с этими задачами готовые решения Marketplace?

Мы проверили на примере пары самых популярных (по количеству установок) решений которые можно попробовать без покупки.

Модуль “reCaptchaFree”

Доступные настройки:

  • поддержка многосайтовости — можно настроить рекапчу для каждого сайта в отдельности;
  • возможность отключения рекапчи без удаления модуля. Правда здесь обнаружилась проблема — при деактивации рекапчи с помощью этой настройки скрипты js все равно подключались на странице;
  • настройка визуального отображения виджета и т.д.

Порадовало, что модуль оказался работоспособен на формах в модальном окне и AJAX-форме. Однако, для работы некоторых компонентов в режиме ajax требуется вносить изменения в код шаблона, что неудобно, если таких компонентов на сайте много.

Также после установки модуля потребуется отредактировать шаблон компонента, чтобы избавиться от подобных ситуаций:
Защита от автоматических сообщений
Как выяснилось позже, это необходимо проделать для всех модулей.

Модуль “Google ReCaptcha – улучшенная капча и защита от ботов”

Состав настроек невелик: только ключи. Поэтому для отключения рекапчи придется удалять модуль. Что касается работоспособности, то с обычными формами модуль справился неплохо. А вот с некоторыми компонентами в режиме Ajax вызвал ошибки. Другие модули (например, Google reCAPTCHA | продвинутая капча) из MarketPlace не предоставляют возможность для тестирования.

Как сделать самим

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

Кастомизация компонента и шаблона компонента

Капча выводится в шаблонах некоторых компонентов. Правильность ее ввода проверяется в компоненте. Почему так? — Потому что: Так архитектурно правильно. MVC и все такое. Шаблон компонента кешируется и выполняется не всегда. Следовательно, без кастомизации компонента здесь никак не обойтись. Прежде, чем кастомизировать компонент, для работы с капчей удобно создать отдельный класс.

class GoogleReCaptcha

{

public static function getPublicKey() { return ‘your_public_key’;}

public static function getSecretKey() { return ‘your_secret_key’;}

/**

   * @return array — if validation is failed, returns an array with errors, otherwise — empty array. This format is expected by component.

   */

  public static function checkClientResponse()

  {

      $context = BitrixMainApplication::getInstance()->

getContext();

      $request = $context->getRequest();

      $captchaResponse = $request->getPost(«g-recaptcha-response»);

      if($captchaResponse)

      {

          $url = ‘https://www.google.com/recaptcha/api/siteverify’;

          $data = array(‘secret’ => static::getSecretKey(), ‘response’

=> $captchaResponse);

          $httpClient = new HttpClient();

          $response = $httpClient->post($url,$data);

          if($response)

              $response = BitrixMainWebJson::

decode($response,true);

          if(!$response[‘success’]) {

              return $response[‘error-codes’];

          }

          return array();

      }

      return array(‘no captcha response’);

  }

}

Пример подключение рекапчи в форму регистрации Используем компонент bitrix:main.register. В этом компоненте предусмотрена стандартная капча.
Скопируем компонент в наше пространство имен директории  /bitrix/components/. Найдем в коде компонента проверку ввода каптчи. Фрагмент из файла  component.php:

// check captcha

   if ($arResult[«USE_CAPTCHA»] == «Y»)

   {

       if (!$APPLICATION->CaptchaCheckCode($_REQUEST[«captcha_word»], $_REQUEST[«captcha_sid»]))

           $arResult[«ERRORS»][] = GetMessage(«REGISTER_WRONG_CAPTCHA»);

   }

В данном фрагменте заменим проверку стандартной капчи на нашу проверку рекаптчи  Google:

if ($arResult[«USE_CAPTCHA»] == «Y»)

   {

       $errorMessages = GoogleReCaptcha::checkClientResponse();

if( !empty($errorMessages)))

           $arResult[«ERRORS»][] = $errorMessages;

   }

Затем отредактируем шаблон компонента. Заменим вывод стандартной капчи на рекапчу:

Фрагмент из файла template.php:

<div class=»g-recaptcha» data-sitekey=»<?=GoogleReCaptcha::getPublicKey()?>»>

Изменения только компонента недостаточно для работы капчи. Также необходимо подключить скрипт для взаимодействия с сервисом. Сделать это следует в файле component_epilog.php компонента.

BitrixMainPageAsset::getInstance()->addString(

“<script src=’https://www.google.com/recaptcha/api.js’></script>”);

В результате получим:

Подключение рекапчи с помощью JS

Можно попробовать пойти другим путем, чтобы не пришлось кастомизировать десятки компонентов. А именно:

  1. При отображении страницы в браузере найдем и подменим все bitrix-капчи на reCAPTCHA.

  2. Будем ловить заполнение форм на любой страницы (все POST-хиты). Если в запросе есть разгаданная пользователем reCAPTHCA заставим битрикс думать, что пользователь разгадал bitrix-капчу.

Вот так будет выглядеть JS-часть с использованием jQuery.

//Находим все битриксовые капчи

b_captcha_sid = $(«[name=’captcha_sid’]»);

if (b_captcha_sid.length > 0) {

  b_captcha_img = $(b_captcha_sid).siblings(‘img’);

  if(b_captcha_img.length >0) {

//Убираем изображения

      $(b_captcha_img).remove();

      $(b_captcha_sid).each(function (index) {

         //Вставляем на место изображений рекапчу

          tmp = document.createElement(‘div’);

          tmp.innerHTML = «<div class=’g-recaptcha’ data-sitekey=’your_site_key’></div>»;

          g_recaptcha = tmp.firstChild;

          g_recaptcha = (this.parentElement).

appendChild(g_recaptcha);

         //Отрисовываем виджет рекапчи

          if(typeof (grecaptcha) != «undefined») {

              grecaptcha.render(g_recaptcha,{

                  ‘sitekey’: ‘your_site_key’

              });

          }

      });

  }

}

//Скрываем все поля ввода слова капчи

b_captcha_word = $(«[name=’captcha_word’]»);

if (b_captcha_word.length > 0) {

  $(b_captcha_word).hide();

}

Компоненты на странице ничего не знают про Google капчу и при отправке формы будут проверять правильность ввода стандартной. Соответственно нам нужно симитировать ее ввод.

Данные HTTP запросов компоненты получают из суперглобальных переменных $_POST, $_GET, $_REQUEST. Для проверки капчи компонент ожидает переменные captcha_sid и captcha_word. captcha_word при отправке формы с рекапчей будет пустая. Ее мы возьмем из таблицы b_captcha.

Изменять суперглобальные переменные  нужно до отработки компонентов. Для этого можно использовать события, которые вызываются в процессе выполнения страницы, а именно OnPageStart или OnBeforeProlog. Вот так будет выглядеть PHP-часть:

$context = BitrixMainApplication::getInstance()-&gt;

getContext();

$request = $context->getRequest();

$captchaResponse = $request->getPost(«g-recaptcha-response»);

if($captchaResponse)

{

if(!GoogleReCaptcha::checkClientResponse())

 {

$captchaSid = $request->getPost(«captcha_sid»);

    if($captchaSid)

    {

//Т.к. нет API, позволяющего получить слово капчи по ID, делаем запрос напрямую к БД

       $dbRes = BitrixMainApplication::getConnection()->query(

«SELECT CODE FROM b_captcha WHERE id='».$captchaSid.»‘»);

       if($res = $dbRes->fetch())

       {

          if($res[‘CODE’])

          {

             $_REQUEST[‘captcha_word’] = $_POST[‘captcha_word’] = $res[‘CODE’];

          }

       }

    }

 }

}

Если пользователь вводил рекапчу и успешно ее прошел, то мы подставляем верное значение captcha_word. В противном случае при проверке капчи компонент выдаст ошибку.

Подключение рекапчи с помощью OnEndBufferContent

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

Пример замены капчи на стороне сервера:

public static function OnEndBufferContent(&$content)

{

//Для форм загружаемых по ajax добавляем вызов скрипта рендера рекапчи

$renderScript = «»;

$htmlId = «»;

$context = BitrixMainApplication::getInstance()->getContext();

$request = $context->getRequest();

if($request->isAjaxRequest())

 {

    $id = uniqid (‘r_’);

    $renderScript = «<script>renderRecaptcha(‘$id’);</script>»;

    $htmlId = ‘id=»‘.$id.'»‘;

 }

//Убираем  поля для ввода слова

$content = preg_replace( ‘/<input[^<>]*names?=s?.captcha_word.[^<>]*>/’ , » , $content );

//Все изображения заменяем на рекапчу

$content = preg_replace ( ‘/<img[^<>]*srcs?=s?./bitrix/tools/captcha.php?(captcha_code|captcha_sid)=[^<>]*>/’ , «<div class=’g-recaptcha’ data-sitekey=»your_site_key» «.$htmlId.»></div>».$renderScript ,  $content);

}

Функция рендера рекапчи на JavaScript выглядит так:

renderRecaptcha = function(elementId) {

if (typeof (grecaptcha) != «undefined») {

    var element = document.getElementById(elementId);

    if(element != undefined && element.childNodes.length == 0) {

       grecaptcha.render(element, {

          ‘sitekey’: ‘your_site_key’

       });

    }

 }

}

Ее следует добавить в шаблон сайта.

Дальнейшая проверка капчи осуществляется также как во втором способе — по событию OnPageStart или OnBeforeProlog.

Сообщения об ошибках

При замене капч разом на всем сайте (способы 2 и 3) нам потребуется изменить сообщение об ошибке ввода капчи. Чтобы избежать подобных ситуаций:
Все сообщения записываются в языковых переменных. Их мы можем переопределить глобально. Создадим файл /bitrix/php_interface/user_lang/ru/lang.php.

Для компонента добавления и редактирования элемента инфоблока запись в файле будет выглядеть так:

$MESS[‘/bitrix/components/bitrix/iblock.element.add.form/lang/ru/component.php’][‘IBLOCK_FORM_WRONG_CAPTCHA’] = «Не пройдена проверка от автоматического заполнения»;

Выводы

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

Задача выглядит не очень сложной. Тем не менее в найденных на MarketPlace решениях она решена с огрехами. Мы исправили эту досадную ситуацию и представляем Вам наш модуль для замены капчи Битрикс на Google reCaptcha.

Понравилась статья? Поделить с друзьями:
  • Ошибка капота w212 мерседес
  • Ошибка кассовая смена не открыта
  • Ошибка капот открыт опель астра j
  • Ошибка кассира при пробитии чека
  • Ошибка капитана klm