Ne v kontakte Asocial programmer's blog

Пишем простой авторегистратор. Часть 3 - боремся с капчей.

Содержание

  1. Инструментарий
  2. Основы
  3. Боремся с капчей
  4. Подключаем антикапчу
  5. Подтверждение по email
  6. Пишем модуль для RegSubmitter

В предыдущей статье мы рассмотрели самый простой пример авторегистратора, которому надо всего лишь отправить форму. Но таких сервисов очень мало, поэтому гораздо чаще приходится во время регистрации видеть перед собой капчу. Сегодня “ляжет под нож” сервис Мое Место.

Шаг 1. Анализ защиты.

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

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

  1. Капча привязывалась к сессии и сессионный идентификатор передавался через cookies
  2. Сессионный ключ передается в скрытом поле формы.
  3. Комбинация первых двух

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

screen29.jpg screen30.jpg

В особо тяжелых случаях таких полей бывает несколько, поэтому надо отследить их все.

Шаг 2. Пишем код.

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

Капчу мы будем вводить ручками, но это только до следующей статьи :)

При написании кода надо обратить внимание на две вещи:

  • HTML-код скрытого поля с сессионным ключом. Основываясь на нем надо будет составлять регулярное выражение.
  • Адрес картинки. При использовании сессионного ключа часто добавляют его к адресу картинки. На это тоже следует обратить внимание.
 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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?php
header('Content-Type: text/html; charset=UTF-8');
function register1()
{
    // Особая, curl-ная магия
    $ch = curl_init(); // Инициализируем сессию
    curl_setopt($ch, CURLOPT_URL,"http://moemesto.ru/register/"); // задаем адрес формы
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Результат нам нужно вернуть в переменную, а не на экран
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Переходить по редиректам
    curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt'); // Указываем файл для хранения кукисов

    // Выполняем запрос
    $result = curl_exec($ch);

    // При помощи простейшего регулярного выражения добываем сессионный ключ
    preg_match('#<input type=hidden name="captchaid" value="([a-f0-9]+)">#i', $result, $key);

    curl_setopt($ch, CURLOPT_URL,"http://moemesto.ru/captcha/$key[1]"); // задаем адрес картинки
    $result = curl_exec($ch); // Скачиваем картинку
    curl_close ($ch); // Закрываем сессию

    file_put_contents('captcha.jpg', $result); // Сохраняем

    return $key[1]; // Возвращаем добытый ключ
}

// Функция, производящая регистрацию
function register2($login, $email, $password, $captcha, $key)
{
    // Все POST-параметры, которые надо отправить
    $post = array(
        'captchaid' => $key, // Передаем сессионный ключ
        'login'     => $login // Логин
        'email'     => $email, // Емейл
        'password'  => $password, // Пароль
        'captcha'   => $captcha, // А это наш код с картинки
        'do_reg'    => 'Зарегистрироваться', // "Нажимаем" кнопку отправить ;-)
    );

    // Особая, curl-ная магия
    $ch = curl_init(); // Инициализируем сессию
    curl_setopt($ch, CURLOPT_URL,"http://moemesto.ru/register/"); // задаем адрес обработчика формы
    curl_setopt($ch, CURLOPT_POST, 1); // Указываем, что нам нужно отправить POST-запрос
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post); // Передаем POST-параметры
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // Результат нам нужно вернуть в переменную, а не на экран
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); // Переходить по редиректам
    curl_setopt($ch, CURLOPT_COOKIEJAR, 'cookie.txt'); // Указываем файл для хранения кукисов. При чем он должен быть тот же, что и в прошлый раз, чтобы кукисы подхватились.

    // Запускаем запрос!
    $result = curl_exec($ch);
    curl_close ($ch); // Закрываем сессию

    // Проверяем на успешность регистрации
    if(strstr($result, 'Поздравляем! Вы успешно зарегистрировались!'))
    {
        return true;
    }
    else
    {
        return false;
    }
}

// Параметры регистрации. Их можно задавать руками, или считывать из файла - на ваше усмотрение.
$login = 'antifrager223';
$email = 'antifrag223@yopmail.com';
$password = 'qwerty';

// Выводим, что мы будем регать
echo "Логин: $login, пароль: $password, email: $email<br/>";

// Если мы уже ввели капчу, то заканчиваем регистрацию
if(!empty($_GET['captcha']))
{
    // Регаем
    if(register2($login, $email, $password, $_GET['captcha'], $_GET['key']))
    {
        echo 'Успешно зарегистрирован';
    else
    {
        echo '<b>Ошибка регистрации</b>';
    }
    echo '<br><a href="'.basename(__FILE__).'">Еще раз</a>';
}
else
{
    // Если капчу еще не ввели - отображаем ее и просим ввести :)
    $key = register1();
    $form = '<h2>Введите код с картинки</h2>
   <img src="captcha.jpg">
   <form>
   <input type="hidden" name="key" value="'.$key.'">
   <input type="text" name="captcha">
   <input type="submit" name="Go!"></form>';
    echo $form;
}
// Все!  ;-)
?>

Вот и все дела. Как и в прошлый раз, в коде есть пара синтаксических ошибок “от дурака”, а в остальном он полностью рабочий, он же есть и во вложении. И, как в прошлый раз, файл должен быть в кодировке UTF-8. Скачать целиком: moemesto.php_.txt

Через неделю…

…нам надоест уже надоело вбивать капчу руками и мы воспользуемся антикапчей.

P.S. Shelf Life theme.