Pull to refresh

Используем «Яндекс.Чистый Веб» для защиты от спама

Reading time5 min
Views27K
Уже достаточно долгое время Яндекс предоставляет бесплатный сервис обнаружения спама в сообщениях под названием «Яндекс.Чистый Веб», однако до сих пор он остаётся малопопулярным.

В этом посте я продемонстрирую основные методы работы с API «Яндекс.Чистый Веб» на примере простого PHP-класса.

Итак, сервис поддерживает четыре метода — обнаружение спама, получение CAPTCHA, проверка введённой CAPTCHA и обжалование решения детектора спама. Мы рассмотрим работу с первыми тремя методами.

Для удобства оформим всё это в виде простого статического класса.

class YandexCW
 {
        public static $api_key          = '12345';
 
        /* URL-адреса */
 
        const check_data_url            = 'http://cleanweb-api.yandex.ru/1.0/check-spam';
        const get_captcha_url           = 'http://cleanweb-api.yandex.ru/1.0/get-captcha';
        const check_captcha_url         = 'http://cleanweb-api.yandex.ru/1.0/check-captcha';
 }


Приступим к реализации методов класса. API «Чистого Веба» принимает GET и POST запросы в зависимости от необходимого метода, и отдаёт результат в формате XML. Поэтому сперва мы напишем в нашем классе несложный приватный метод для отправки запросов и чтения ответов. Будем использовать SimpleXML для чтения ответов, а вот CURL применять не станем — благо, стандартная функция file_get_contents позволяет совершать и GET- и POST-запросы с помощью контекстов.


    /* Отправка запроса сервису */ 

    private function xml_query($url, $parameters = array(), $post = false) 
     { 
        if (!isset($parameters['key'])) $parameters['key'] = self::$api_key; 

        $parameters_query = http_build_query($parameters); 

        if ($post) 
         { 
            $http_options = array( 
                    'http'    => array ( 
                        'method'     => 'POST', 
                        'content'    => $parameters_query 
                     ) 
             ); 

            $context = stream_context_create($http_options); 
            $contents = file_get_contents($url, false, $context); 

         } else $contents = file_get_contents($url.'?'.$parameters_query); 

        if (!$contents) return false; 

        $xml_data = new SimpleXMLElement($contents); 

        return $xml_data; 
     }


Этот метод существенно упростит нам работу с API — он автоматически подставляет ключ, формирует контекст для file_get_contents, если нам понадобится сделать POST-запрос, а также возвращает ответ уже в виде объекта SimpleXML. Думаю, код не нуждается в более подробном комментировании. Так что перейдём непосредственно к методам для работы с API.

Проверка сообщения на спам


В первую очередь реализуем метод для отправки содержимого сообщения Яндексу и последующей проверки его на спам. Однако перед тем, как просто привести код, следует кое-что уточнить. Согласно описанию метода check-spam, он может принимать следующие параметры, касающиеся содержимого сообщения:

  • ip — IP-адрес отправителя.
  • email — Адрес электронной почты отправителя.
  • name — Имя отправителя, отображаемое в подписях к сообщениям.
  • login — Имя учетной записи пользователя на ресурсе.
  • realname — ФИО пользователя взятые, например, из его регистрационных данных.
  • subject-plain — Тема поста в формате text/plain.
  • subject-html — Тема поста в формате text/html.
  • subject-bbcode — Тема поста в формате BBCode.
  • body-plain — Содержимое (тело) комментария или поста в формате text/plain.
  • body-html — Содержимое (тело) комментария или поста в формате text/html.
  • body-bbcode — Содержимое (тело) комментария или поста в формате BBCode.


Набор отправляемых на проверку данных может быть произвольным, за исключением того, что из семейства параметров body и subject может быть указан лишь один тип — или plain, или html, или bbcode. Обязательных параметров также нет. Поэтому передавать все эти данные нашему методу мы будем не идущими последовательно параметрами, а одним массивом с произвольным набором данных.


    /* Проверка на спам */ 

    public function is_spam($message_data, $return_full_data = false) 
     { 
        if (!isset($message_data['ip'])) $ip = $_SERVER['REMOTE_ADDR']; 

        $response = self::xml_query(self::check_data_url, $message_data, true); 
        $spam_detected = (isset($response->text['spam-flag']) && $response->text['spam-flag'] == 'yes'); 

        if (!$return_full_data) return $spam_detected; 

        return array( 
                    'detected'        =>  $spam_detected, 
                    'request_id'    => (isset($response->id)) ? $response->id : null, 
                    'spam_links'    => (isset($response->links)) ? $response->links : array() 
         ); 
     }


Данный метод позволит нам отправлять данные на проверку с автоматической подстановкой IP-адреса пользователя. В зависимости от второго параметра, функция может возвращать либо просто true или false, либо массив с подробной информацией, содержащий список ссылок, заподозренных как спамерские, а также сгенерированный Яндексом id запроса. Он нам, кстати, далее пригодится.

Получение CAPTCHA


Яндекс предлагает нам воспользоваться его собственной «капчей» и надо сказать, что у этого решения есть очевидные плюсы — во-первых, снижается нагрузка на наш сервер, а во-вторых, забота о «взломоустойчивости» CAPTCHA ложится на плечи «Яндекса». Метод будет предельно простым:

    /* Получение CAPTCHA */ 

    public function get_captcha($id = null) 
     { 
        $response = self::xml_query(self::get_captcha_url, array('id' => $id)); 

        if (!$response || !isset($response->captcha)) return false; 

        return array('captcha_id' => $response->captcha, 'captcha_url' => $response->url); 
     }


Как видно из предпоследней строки, метод возвращает ID «капчи» и ссылку на само изображение.
Ссылка, как правило, имеет следующий вид:
u.captcha.yandex.net/image?key=CAPTCHA ID

Лучше использовать оба выдаваемых параметра, чтобы защита не сломалась, если Яндекс что-нибудь изменит в формате ссылки.

Проверка CAPTCHA


Наконец, третий метод класса будет использоваться для проверки введённого пользователем значения CAPTCHA.
Чтобы им воспользоваться, нам надо будет передать ему id «капчи», выданный предыдущим методом, а также то, что ввёл пользователь. Не лишним будет также передать и id запроса, который мы получили, когда отправляли сообщение на проверку, однако это необязательно.

    /* Проверка CAPTCHA */ 

    public function check_captcha($captcha_id, $captcha_value, $id = null) 
     { 
        $parameters = array( 
                            'captcha'        => $captcha_id, 
                            'value'        => $captcha_value, 
                            'id'            => $id 
         ); 

        $response = self::xml_query(self::check_captcha_url, $parameters); 

        return isset($response->ok); 
     }


Примеры использования


Для полноценной проверки системы «Чистого Веба» можно загрузить простой демонстрационный скрипт. Перед проверкой не забудьте получить свой ключ API «Чистого Веба» и указать его в скрипте!
Можно также скачать класс отдельно или посмотреть его полный код в браузере.

Проверка содержимого формы:
// Вызываем класс и задаём свой ключ API
 
require('YandexCW.class.php');
YandexCW::$api_key = '12345';
 
// Отправляем данные формы на проверку
 
$allowed_keys = array('email', 'name', 'login', 'realname', 'subject-plain', 'body-plain');
$post_data = array_intersect_key($_POST, array_fill_keys($allowed_keys, null));
 
$is_spam = YandexCW::is_spam($post_data, true);
 
// Выводим итоги проверки
 
var_dump($is_spam);
 


Особенности


Большинство параметров при вызове методов API являются необязательными.
Например, можно не использовать проверку на спам, а просто подключить себе CAPTCHA «Яндекса», аналогично тому, как подключают ReCAPTCHA.
Подробнее — на api.yandex.ru.
Tags:
Hubs:
Total votes 52: ↑46 and ↓6+40
Comments28

Articles