Как добавить ReCAPTCHA на свой сайт
Недавно столкнулся с тем, что боты поумнели настолько, что начали обходить обычную CAPTCHA на одном из сайтов, поддержкой которых я занимаюсь. Пришлось искать альтернативные решения, и выбор пал на reCAPTCHA от Google. Как выяснилось, подключить ее достаточно просто. Нужно зарегистрировать свой сайт на странице ReCAPTCHA (нужно иметь учетную запись в Google) и получить пару ключей: публичный (он будет размещаться на сайте) и секретный, который будет храниться только на сервере.
Дальше в форму, для которой нужна проверка CAPTCHA вставляем код такого вида:
<script src='https://www.google.com/recaptcha/api.js'></script>
<div class="g-recaptcha" data-sitekey="ваш-публичный-ключ"></div>
Google рекомендует вставлять тег script после head, однако на самом деле это не обязательно, и можно вставить его и прямо в форму или вообще в конец страницы перед </body>. Последний вариант, пожалуй, даже предпочтительнее, так как в этом случае код будет загружаться в самом конце загрузки страницы и не будет ее замедлять.
Если вы все сделаете правильно, то в том месте сайта, куда вы вставили код, появится такой блок:

В нем же будет скрытое поле g-recaptcha-response, которое будет отправлено на сервер вместе с данными формы. Для проверки корректности прохождения CAPTCHA нам нужно сделать POST-запрос на сервер Google.Запрос делается на адрес https://www.google.com/recaptcha/api/siteverify, в нем в параметре secret передается секретный ключ, полученный при регистрации, а в параметре response — код ответа из поля g-recaptcha-response. В ответ возвращается JSON-объект, в котором нужно проверить поле success.
На PHP со включенной опцией allow_url_fopen код проверки будет выглядеть выглядеть так:
$valid_captcha = false;
if (!empty($_POST['g-recaptcha-response'])) {
$postdata = http_build_query(
array(
'secret' => 'ваш-секретный-ключ',
'response' => $_POST['g-recaptcha-response']
)
);
$opts = array('http' =>
array(
'method' => 'POST',
'header' => 'Content-type: application/x-www-form-urlencoded',
'content' => $postdata
)
);
$context = stream_context_create($opts);
$result = file_get_contents('https://www.google.com/recaptcha/api/siteverify', false, $context);
$valid_captcha = strpos($result,'"success": true')!==false;
}
if (!valid_captcha) {
// выводим сообщение об ошибке
}
else {
// выполняем запрошенное пользователем действие
}
Если опция allow_url_fopen на сервере выключена, можно воспользоваться моей библиотекой Requests, которая делает запрос через модуль curl. В этом случае код приобретает вид:
require_once('Requests.php');
$valid_captcha = false;
if (!empty($_POST['g-recaptcha-response'])) {
$rq = new Requests();
$result = $rq->post('https://www.google.com/recaptcha/api/siteverify', array(
'secret' => 'ваш-секретный-ключ',
'response' => $_POST['g-recaptcha-response']
));
$valid_captcha = strpos($result,'"success": true')!==false;
}
if (!valid_captcha) {
// выводим сообщение об ошибке
}
else {
// выполняем запрошенное пользователем действие
}
Отмечу, что в коде применяется такой трюк: вместо полноценного парсинга JSON-объекта этот объект рассматривается как строка, в которой проверяется наличие подстроки "success": true. Делается это для двух целей: экономия ресурсов сервера (поиск подстроки в строке — значительно менее затратная операция, чем полноценный разбор JSON) и независимость от наличия на сервере модуля JSON. Это уместно в случае простых API, где полей в ответе мало, и известно, что они не будут меняться, однако в более сложных случаях лучше к таким трюкам не прибегать.
Если проанализировать плюсы и минусы этого решения, получаем следующее.
Преимущества:
- Простота добавления в любой проект
- Высокая надежность с точки зрения защиты от ботов (а кроме того, по мере роста интеллекта ботов Google может вводить дополнительные меры по защите, при этом они будут применяться сразу же, без каких-либо дополнительных мер с вашей стороны)
- Статистика по доле пользователей, прошедших CAPTCHA и некоторые возможности регулировки ее сложности.
- Критическая зависимость от внешнего сервиса: если по каким-то причинам перестанет работать ReCAPTCHA (например, очередные «ковровые блокировки» Роскомнадзора или взлом Google-аккаунта, на котором были получены публичный и приватный ключи), то станут недоступными ключевые действия на сайте (такие как регистрация или оформление заказа).
- Если с одного адреса ходит много пользователей (а это типичная ситуация для мобильных 3G-сетей и провайдеров, подключающие пользователей через NAT), reCAPTCHA потребует от пользователя довольно большого количества действий по распознаванию картинок, что вызовет его раздражение.
Блять что вы за дятлы не один не скажет куда ставить серверную часть кода