Нужна простенькая капча
От: Кодт Россия  
Дата: 23.07.07 10:39
Оценка:
Какие-то дебилы сыплют в мою гостевую книгу всякий хлам.
Дебилизм выражается в том, что гостевуха премодерируемая, и кроме меня, никто не увидит их энларджа.

Судя по разбросу IP — это зомби-нет, а не обычные анонимайзеры. Поэтому бан-лист не работает
Один раз поменял url странички — поток прервался где-то на месяц. Видимо, хозяин всё-таки пасёт её.

Что посоветуете?
Желательно, не громоздкое. Может быть, даже вообще текстовую капчу. А может, и без капчи можно обойтись?
И желательно, с комментариями — чтобы я научился (например, до сих пор не вкурил в механизм сессий).

Язык — PHP4.

Заранее спасибо.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re: Нужна простенькая капча
От: Дм.Григорьев  
Дата: 23.07.07 11:06
Оценка: 24 (1)
Здравствуйте, Кодт, Вы писали:

К>Язык — PHP4.


У меня есть только для PHP5: работающий пример. Подогнать и проверить под PHP4 не могу — нет его у меня. Там, по идее, достаточно убрать в файле класса всякие public/private (у переменных заменить на var).

Аннотация: PHP5-класс CCaptcha, генерирует фразу и картинку для Теста Тьюринга. Гибкие настройки в конструкторе класса. Сгенерированную фразу записывает в $_SESSION['captcha'], картинку выводит напрямую вместе с заголовками, без временных файлов.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
http://dimgel.ru/lib.web — thin, stateless, strictly typed Scala web framework.
Re: Нужна простенькая капча
От: Mamut Швеция http://dmitriid.com
Дата: 23.07.07 11:15
Оценка:
К>Что посоветуете?
К>Желательно, не громоздкое. Может быть, даже вообще текстовую капчу. А может, и без капчи можно обойтись?
К>И желательно, с комментариями — чтобы я научился (например, до сих пор не вкурил в механизм сессий).

Есть, например, reCaptcha. Помогает оцифровывать книги

Я у себя использую самописную функцию, предлагаюущую решить простенькую задачку типа 2+2:

(только не смейтесь над убогим )
// generate math expression for sanity checks
function gen_check() {
    $no = array(1, 2, 3, 4, 5, 6, 7, 8, 9);
    $op = array('+', '-', '*');

    $arr = array();

    $no1 = $no[mt_rand(0, 8)];
    $no2 = $no[mt_rand(0, 8)];
    $opp = $op[mt_rand(0, 2)];

    $ee = 0;

    eval('$ee = '.$no1.' '.$opp.' '.$no2.';');

    return array($no1, $no2, $opp, bin2hex(md5(des($ee), TRUE)));
}

function test_check($result, $answer)
{
    return bin2hex(md5(des(trim($answer)), TRUE)) == $result;
}


использование:

В HTML:
<?php list($no1, $no2, $operator, $result) = gen_check(); ?>

<label for="check">Чему равно <strong><?php echo $no1.$operator.$no2 ?></strong></label>
<br />
<input type="text" size="20" name="answer" />

<br />
<br />
<input type="hidden" name="result" value="<?php echo $result ?>" />


при обработке данных:
$result = $_REQUEST['result'];
$answer = $_REQUEST['answer'];

if(test_check($result, $answer))
    echo 'Наш человек :) ';


dmitriid.comGitHubLinkedIn
Re: Нужна простенькая капча
От: ibnTeo Россия http://ibnteo.klava.org/
Дата: 23.07.07 11:47
Оценка: 5 (1)
К>Какие-то дебилы сыплют в мою гостевую книгу всякий хлам.
К>Дебилизм выражается в том, что гостевуха премодерируемая, и кроме меня, никто не увидит их энларджа.

К>Судя по разбросу IP — это зомби-нет, а не обычные анонимайзеры. Поэтому бан-лист не работает

К>Один раз поменял url странички — поток прервался где-то на месяц. Видимо, хозяин всё-таки пасёт её.

К>Что посоветуете?

К>Желательно, не громоздкое. Может быть, даже вообще текстовую капчу. А может, и без капчи можно обойтись?
К>И желательно, с комментариями — чтобы я научился (например, до сих пор не вкурил в механизм сессий).

К>Язык — PHP4.


Я сделал простое решение на клиенте, работает пока

<form action="break.php" ...> <!-- здесь ловушка для роботов - break.php не кладет данные в базу -->
...
<checkbox onclick="this.form.action='save.php'; this.form.elements['subm'].disabled=false;" /> - согласен (с чем угодно)
<input type="submit" name="subm" value="Отправить" disabled="disabled" />
</form>

принцип работы: без выбора галки не дает отпавить форму, при выборе меняет action у формы на правильный
Re[2]: Нужна простенькая капча
От: MBy Украина http://maxim.vuets.name/
Дата: 23.07.07 12:34
Оценка:
Здравствуйте, ibnTeo, Вы писали:

T>Я сделал простое решение на клиенте, работает пока


T>
<form action="break.php" ...> <!-- здесь ловушка для роботов - break.php не кладет данные в базу -->
T>...
T><checkbox onclick="this.form.action='save.php'; this.form.elements['subm'].disabled=false;" /> - согласен (с чем угодно)
T><input type="submit" name="subm" value="Отправить" disabled="disabled" />
T></form>

T>принцип работы: без выбора галки не дает отпавить форму, при выборе меняет action у формы на правильный

По идее, можно сделать и без галочки — менять сразу при submit-е. Вот только за что я не люблю такие методики так за то, что они вообще делают невозможным работу формы при выключенном JS.

Кстати, «в тему»: наткнулся вчера на обсуждение небольшое о методах борьбы с зло-роботами (: — CSS и борьба со спамом.
Hoc est simplicissimum!
Re[2]: Нужна простенькая капча
От: Кодт Россия  
Дата: 23.07.07 12:53
Оценка:
Здравствуйте, Mamut, Вы писали:

<>
Боюсь, что такая капча элементарно ломается.
Спамер будет присылать POST-запрос с согласованной парой вопроса и ответа. Ведь не жмёт же компьютер-зомби кнопки на страничке?
То же касается и яваскрипта.

Поэтому и хочу разобраться с сессиями или другими механизмами диалога между сервером и клиентом.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Нужна простенькая капча
От: Mamut Швеция http://dmitriid.com
Дата: 23.07.07 13:21
Оценка:
К><>
К>Боюсь, что такая капча элементарно ломается.
К>Спамер будет присылать POST-запрос с согласованной парой вопроса и ответа. Ведь не жмёт же компьютер-зомби кнопки на страничке?
К>То же касается и яваскрипта.

К>Поэтому и хочу разобраться с сессиями или другими механизмами диалога между сервером и клиентом.


Ну, значение $result можно и в сессию класть, а потом проверять Да и саму схему шифрования менять хоть десять раз на дню. Но это так, поделка

Можно использовать reCaptcha
Или написать свою собственную...


dmitriid.comGitHubLinkedIn
Re[4]: Нужна простенькая капча
От: MBy Украина http://maxim.vuets.name/
Дата: 23.07.07 13:42
Оценка: 91 (2)
Здравствуйте, Mamut, Вы писали:

M>Можно использовать reCaptcha

M>Или написать свою собственную...

Если на то пошло…
http://captcha.ru/kcaptcha/ да и вообще сам http://captcha.ru/
Забавные вещи на http://ocr-research.org.ua/
http://www.cryptographp.com/
http://captcha.opti-mail.net/ необычная и замутная, но оригинальная (:
Hoc est simplicissimum!
Re[2]: Нужна простенькая капча
От: Кодт Россия  
Дата: 23.07.07 13:54
Оценка:
Здравствуйте, Дм.Григорьев, Вы писали:

Спасибо за скрипт.
Я, кажется, вкурил в сессии. Вот здесь. http://www.phpfaq.ru/sessions

Действующий макет гостевухи (минимальный пример) приведён ниже.
А в реальности там будет, естественно, дофига проверок, запись в базу и проч, и проч.
<?
/////////
// gb.php

// сессию надо открывать перед отправкой заголовков,
// т.е. перед первым выводом html-я
session_start();
?>
<html>
<head>
<title>guest book</title>
</head>
<body>
<div>Hello!</div>
<?

// проверка - это post-запрос от моей формы, или что-то иное?
function isreply()
{
    return isset($_REQUEST['posted']);
}
// получение капчи из сессии и из запроса
function getcaptcha($t)
{
    if($t)
        return $_SESSION['captcha'];
    else if(isset($_REQUEST['captcha']))
        return $_REQUEST['captcha'];
    else
        return;
}
// проверка капчи
function checkpost()
{
    $good = getcaptcha(true);
    $test = getcaptcha(false);
    if(!isset($good))
        return 'failed to establish the session';
    if(!isset($test))
        return 'failed to accept the form';
    if($test != $good)
        return "expected $good, accepted $test";
    return;
}
// вот так я покажу форму
function showform()
{
    $digit = mt_rand(0,9);
    $names = array('zero','one','two','three','four','five','six','seven','eight','nine');
    $test = $names[$digit];
    $_SESSION['captcha'] = $digit;
?>
<form method=post action=gb.php>
<table>
<tr><td>Your name:</td><td><input type=text name=who value=''></input></td></tr>
<tr><td>Your email:</td><td><input type=text name=eml value=''></input></td></tr>
<tr><td>Your homepage:</td><td><input type=text name=url value=''></input></td></tr>
<tr><td>Your opinion:</td><td><input type=text name=msg value=''></input></td></tr>
<tr><td>Please type in the digit '<?= $test ?>':</td><td><input type=text name=captcha value=''></input></td></tr>
<tr><td>&nbsp;</td><td><input type=submit value='Send!'></td></tr>
</table>
<input type=hidden name=posted value=1></input>
</form>
<?
}//showform()

// вот так я покажу еггог
function showerror($err)
{
?><div><b>Error!!! <?= $err ?></b></div><?
}

// вот так я покажу результат ввода
function showresult()
{
    $who = $_REQUEST['who'];
    $url = $_REQUEST['url'];
    $eml = $_REQUEST['eml'];
    $msg = $_REQUEST['msg'];
?>
<div>You have posted:
<ul>
    <li>Name = <?= htmlspecialchars($who) ?></li>
    <li>URL = <?= htmlspecialchars($url) ?></li>
    <li>email = <? htmlspecialchars($eml) ?></li>
    <li>msg = <? htmlspecialchars($msg) ?></li>
</ul>
</div>
<?
}

// собственно, план работ:
if(isreply())
{
    $err = checkpost();
    if(isset($err))
    {
        showerror($err);
        showform();
    }
    else
    {
        showresult();
    }
}
else
{
    showform();
}

?>
</body>
</html>
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[3]: Нужна простенькая капча
От: . Великобритания  
Дата: 23.07.07 14:14
Оценка:
Кодт wrote:

> Боюсь, что такая капча элементарно ломается.

> Спамер будет присылать POST-запрос с согласованной парой вопроса и
> ответа. Ведь не жмёт же компьютер-зомби кнопки на страничке?
> То же касается и яваскрипта.
> Поэтому и хочу разобраться с сессиями или другими механизмами диалога
> между сервером и клиентом.
Сессии и другие механизмы диалога делаются браузером, т.е. программой, а следовательно могут быть запрограммированны в
роботе. Только фигни типа посчитать арифметическое выражение нарисованное на картинке могут отшить роботов.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[3]: Нужна простенькая капча
От: Дм.Григорьев  
Дата: 23.07.07 14:37
Оценка: 25 (1)
Здравствуйте, Кодт,

Да, всё выглядит правильно. Два мелких замечания:

1. Лучше всюду писать <?php вместо <? (хотя у большинства хостеров включена deprecated-опция short tags, из-за чего приходится, например, при генерации XML писать так: echo '<' . '?xml ...')

2. На случай вызова showform() из обработчика ошибок, следовало бы подставлять в поля формы ранее введённые юзером значения (что-то типа <input ... value="<?php = @_REQUEST['...']'; ?> .../>, если подавление hint-ов с помощью '@' тебя не смущает).
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
http://dimgel.ru/lib.web — thin, stateless, strictly typed Scala web framework.
Re[4]: Нужна простенькая капча
От: Кодт Россия  
Дата: 23.07.07 15:32
Оценка:
Здравствуйте, ., Вы писали:

.>Сессии и другие механизмы диалога делаются браузером, т.е. программой, а следовательно могут быть запрограммированны в роботе. Только фигни типа посчитать арифметическое выражение нарисованное на картинке могут отшить роботов.


Сессии только наполовину делаются браузером. На другую половину — таки сервером.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: Нужна простенькая капча
От: . Великобритания  
Дата: 23.07.07 17:07
Оценка:
Кодт wrote:

> Сессии только наполовину делаются браузером. На другую половину — таки

> сервером.
Клиент легко может при каждом запросе создавать новую сессию (или если совсем крутой робот, то брать из пула ранее
начатых). Так что "серверная часть" никакой роли играть не может.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[6]: Нужна простенькая капча
От: Кодт Россия  
Дата: 24.07.07 08:08
Оценка:
Здравствуйте, ., Вы писали:

.>Клиент легко может при каждом запросе создавать новую сессию (или если совсем крутой робот, то брать из пула ранее начатых). Так что "серверная часть" никакой роли играть не может.


Ну и что он с этого добьётся? Ну наоткрывает новых сессий, ни в одной из них капчу правильно не введёт, этим всё и закончится.
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[7]: Нужна простенькая капча
От: . Великобритания  
Дата: 24.07.07 20:20
Оценка:
Кодт wrote:

> .>Клиент легко может при каждом запросе создавать новую сессию (или если

> совсем крутой робот, то брать из пула ранее начатых). Так что "серверная
> часть" никакой роли играть не может.
>
> Ну и что он с этого добьётся? Ну наоткрывает новых сессий, ни в одной из
> них капчу правильно не введёт, этим всё и закончится.
Аа.. Ты людей прошедших капчу хочешь запоминать? Тогда ладно. Просто ты упоминул это дело в контексте "капча элементарно
ломается", вот я и подумал, что ты хочешь придумать как использовать сессии для усиления капчи, я просто хотел сказать,
что сессии помочь ничем не могут.
Posted via RSDN NNTP Server 2.1 beta
но это не зря, хотя, может быть, невзначай
гÅрмония мира не знает границ — сейчас мы будем пить чай
Re[8]: Нужна простенькая капча
От: Кодт Россия  
Дата: 25.07.07 08:29
Оценка:
Здравствуйте, ., Вы писали:

>> Ну и что он с этого добьётся? Ну наоткрывает новых сессий, ни в одной из

>> них капчу правильно не введёт, этим всё и закончится.
.>Аа.. Ты людей прошедших капчу хочешь запоминать? Тогда ладно. Просто ты упоминул это дело в контексте "капча элементарно ломается", вот я и подумал, что ты хочешь придумать как использовать сессии для усиления капчи, я просто хотел сказать, что сессии помочь ничем не могут.

Запоминать мне их не надо. Сценарий примерно такой:
1) юзер кликнул в гостевухе на "добавить": открыл сессию, создал вопрос-ответ; показал страницу ввода с этим вопросом
2) получил post-запрос с ответом: (повторно) открыл сессию; сравнил со значением, запомненным на сервере; записал в базу; закрыл сессию

Если спамбот сразу прыгнет на (2) — в сессии не будет контрольного значения, и я пошлю его нафиг.

Только нужно таймаут у сессии выставить — чтобы не хранить хлам на сервере.



А пока что я сделал ещё проще: дебильный байесвский фильтр.
Если в тексте сообщения нет русских букв — это спам
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[4]: Нужна простенькая капча
От: Кодт Россия  
Дата: 25.07.07 08:29
Оценка:
Здравствуйте, Дм.Григорьев, Вы писали:

ДГ>2. На случай вызова showform() из обработчика ошибок, следовало бы подставлять в поля формы ранее введённые юзером значения


В настоящей гостевухе так и сделано. Здесь был макет.
Но, пожалуй, я её немножко отрефакторю.

ДГ> (что-то типа <input ... value="<?php = @_REQUEST['...']'; ?> .../>, если подавление hint-ов с помощью '@' тебя не смущает).


А что за тема с хинтами? Еггог, если элемент массива отсутствует?
... << RSDN@Home 1.2.0 alpha rev. 655>>
Перекуём баги на фичи!
Re[5]: Нужна простенькая капча
От: Дм.Григорьев  
Дата: 25.07.07 08:54
Оценка: 25 (1)
Здравствуйте, Кодт, Вы писали:

ДГ>> (что-то типа <input ... value="<?php = @_REQUEST['...']'; ?> .../>, если подавление hint-ов с помощью '@' тебя не смущает).


К>А что за тема с хинтами? Еггог, если элемент массива отсутствует?


Если ты обращаешься к несуществующей переменной, e.g. к несуществующему элементу массива $_REQUEST['xxx'], то будет сгенерировано предупреждение уровня NOTICE (самое слабое). Чтобы оно не выводилось в стандартный вывод (красным текстом), можно поступить двояко:

1) гасить вывод всех сообщений определённого уровня с помощью error_reporting(E_ALL & ~E_NOTICE);

2) гасить вывод всех сообщений для конкретного оператора с помощью префикса '@', например:
— @$_REQUEST['xxx'] — гасится вывод сообщения "Undefined variable";
— @imap_open(...), @unlink(...) — гасится вывод сообщений из методов (при этом функции работают без изменений, т.е. остаются доступными коды возвратов и imap_errors()).

Однако, оба эти способа подавления отладочного вывода не катят, если ты инсталлируешь обработчик ошибок через set_error_handler() — например, для журналирования. Обработчик будет вызываться с типом ошибки NOTICE, даже если ты напишешь @$_REQUEST['xxx'], в итоге журнал будет засоряться всякой фигнёй. Поэтому я обычно оборачиваю работу с $_REQUEST в простенький класс, чтобы избежать генерации "Undefined variable" NOTICE:

class Request {

// PUBLIC:

    function __construct($array = NULL) {
        $this->data = $array ? $array : $_REQUEST;
    }
    
    function getAll() {
        return $this->data;
    }    

    function get($name, $default = NULL) {
        return isset($this->data[$name]) ? $this->data[$name] : $default;
    }
    
// PRIVATE:

    private $data;
}
?>


В большинстве проектов я использую более навороченную версию, с интерфейсом вроде следующего:

[php]
class Request {

// R=required, T=trim, E=treat empty as missing.
function get($name, $options = 'RTE', $default = NULL);

function getString($name, $options = 'RTE', $default = "", $regexp = NULL);
function getInt($name, $options = 'RTE', $default = 0, $min = 1, $max = NULL);
function getBoolean($name, $options = 'RTE', $default = 0);
function getEmail($name, $options = 'RTE', $default = "");
...
}

и с реализациями для $_REQUEST и raw-posted XML. Тут, правда, проблемы с нормальной обработкой ошибок (с генерацией контекстно-зависимых и локализованных сообщений), но в целом идея себя оправдывает.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
http://dimgel.ru/lib.web — thin, stateless, strictly typed Scala web framework.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.