Аз намирам CAPTCHA за непрактична. Идеята й е да отсява спам-бота, но същия успех тя постига сред доброжелателния потребител. Има CAPTCHA доведена до състояние на "разшифроване" и нещата се свеждат до гадаене, и проба-грешка. При неуспех, смятайте този потребител изгубен за каузата на вашия проект. По-важното е, че спамърите включиха в своята атака човешки ресурс - кликъри. За 1000 разпознати CAPTCHA те плащат по 1$. Индия и Китай са първенци в това отношение. Други спамъри пък предлагат безплатно порно, след като покажат същата CAPTCHA на порноманиаците. Изобретения, които занижават смисъла на CAPTCHA.
В този ред на мисли, реших да споделя начин за проста CAPTCHA, която се базира на математически израз. Колко прави 2 + 3. Правилен отговор и формата събмитната.
Алгоритъмът на подобна реализация е прост. Генериране на две числа в диапазон от 0 до 10. Съхраняване в сесионна-променлива резултата от техния сбор. При отправяне на данните от потребителя сравняване на резултатите - съхранения и потребителския. При съвпадение - имаме човек, иначе не издържана проверка и генерация на нови две числа с предложение за нова проба.
Очакваната критика е, че възможните комбинации от сбора на две числа в подобен диапазон е много малък. Висшата математика разглежда този въпрос в раздели комбинаторика и теория на вероятностите.
Да, малък е. Съгласете се, че предложението за смятане на двуцифрени числа затруднява потребителя, особено трицифрени и нагоре. Тогава позволете да насоча мислите в друга посока.
Потребителят винаги първоначално посещава страницата с HTML-форма, а после бива пренасочен към обработчика й, намиращ се на адрес различен от Web-формата. Общото в два случая е един и същи IP, и един и същи user agent (браузър). Роботите не спазват това правило. Те сканират страницата и се насочват към целевата страница указана в action="" на формата. Защо да не впрегнем тази особеност? Конкретно за нашата форма, Spambot е длъжен да ползва един и същи IP и агент ID при сканиране, и атака.
В скрито поле слагам хеш от IP адреса уловен при зареждане на Web-формата. Събмита на формата изпраща това значение, а на страницата на обработчика подлагам на сравнение. Друга идея е да се добави мним Input, който да бъде скрит от CSS (display:none;). Потребителят няма да вижда това поле, докато робота ще се опита да го запълни. Съдържанието му проверяваме с функция empty(). А още, да се зададе задължителен интервал от време. На човек му е нужно време да осмисли и запълни формата, преди да я изпрати, докато робота атакува веднага.
Това е Web-формата. Разполага с едно поле, в което потребителят посочва името си, текстово поле, в което да пише, още едно поле за въвеждане на пресмятането. Бутон изпрати и бутон изчисти.
Web-формата e изложена с учебна цел. Спартански вид, без стилове. Тя никъде не води и подписването й ще презарежда страницата на блога ми. Не се заигравайте с бутон "Юруш". Кой не е гледал екшън филма "Юруш на маслините", значи никога не е мечтал за двукасетъчен магнетофон.
Претендирам полетата да съдържат миниум два символа. Името ограничавам до 32 символа, а текста до 2048. Едва ли желаете, да получавате фермани и супер-дупер имена. При успех пращам данните на електронната си поща. Без JavaScript. Истинската проверка винаги на страна на сървъра извършвайте. JavaScript като помощно средство, като съветник и ни повече.
Код на формата
<?php session_start(); $a = rand(0,9); $b = rand(0,9); $_SESSION['res'] = $a + $b; $_SESSION['adrress'] = $_SERVER['PHP_SELF']; $_SESSION['agent'] = $_SERVER['HTTP_USER_AGENT']; $ip = md5($_SERVER['REMOTE_ADDR']); ?> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>ProCapcha</title> </head> <body> <form action="processor.php" method="POST"> <fieldset><legend>Обратна връзка</legend> <p><label>Потребител <input type="text" name="name" size="17" placeholder="Вашето име"></label></p> <p><label>Коментар <textarea name="comment" rows="10" placeholder="Напишете коментар"></textarea></label></p> <p><?php echo $a. ' + ' .$b.' = ';?><input type="text" name="res" size="1" maxlength="2" placeholder="?" required></p> <p><input type="submit" name="submit" value="Юруш"> <input type="reset" value="Изчисти"></p> <input type="hidden" name="tracker" value="<?= $ip ?>"> <?php echo $_SESSION['mes']; unset($_SESSION['mes']); ?> </fieldset> </form> </body> </html>
Елемент $_SERVER['PHP_SELF'] съдържа името на скрипта, отчитайки корневата директория на хоста, Като правило, това е част от друг фрагмент $_SERVER['SCRIPT_NAME']. Ползата от него, е че името на скрипта търпи произволна смяна при бъдещи манипулации. Не хардкодвам името на скрипта. Присвоявам го на поредна сесионна променлива.
С $_SERVER['HTTP_USER_AGENT'] засичам браузъра на госта. Идеята описана горе, а съдържанието на $_SERVER['REMOTE_ADDR'] хеширам, за да го предам на скритото поле на формата.
Следва Web-формата в стил HTML5, като в тялото й добавям място за извеждане на съобщения, който биват в последствие анихилирани.
Просто като боб!
Код на обработчика
<?php session_start(); header ('Content-type:text/html;charset=utf-8'); if($_POST['track'] == md5($_SERVER['REMOTE_ADDR'])){ if($_SESSION['agent'] == $_SERVER['HTTP_USER_AGENT']){ if((int)trim($_POST['res']) == $_SESSION['res']){ $name = trim($_POST['name']); $comment = trim($_POST['comment']); if((mb_strlen($name, 'utf-8') > 2) && (mb_strlen($comment, 'utf-8') > 2)) { $name = mb_substr($name, 0, 32, 'utf-8'); $comment = mb_substr($comment, 0, 2048, 'utf-8'); } else { $_SESSION['mes'] = '<p>Моля, запълнете формата!</p>'; header("Location: {$_SESSION['adrress']}"); exit; } $to = 'profruit@abv.bg';//вашия e-mail адрес $subject = 'Коментар от сайта';// заглавие на писмото $body = $comment;//тяло $headers = 'From:'.$name.' <you@example.com>' . "\n"; $headers .= 'Content-type:text/plain; Charset=utf-8'; if(mail($to, $subject, $body, $headers)){ $_SESSION['mes'] = '<p>Писмото изпратено!</p>'; header("Location: {$_SESSION['adrress']}"); exit; } else{ $_SESSION['mes'] = '<p>Моля, опитайте пак по-късно!</p>'; header("Location: {$_SESSION['adrress']}"); exit; } } else{ $_SESSION['mes'] = '<p>Въведен грешен отговор!</p>'; header("Location: {$_SESSION['adrress']}"); exit; } } else{ exit('Huston, You have a problem!'); } } else if(!empty($_SESSION['adrress'])){ header("Location: {$_SESSION['adrress']}"); exit; } else{ exit('Huston, You have a problem!'); }
Има маргинали, които гледат изходния код и подобно на роботите се обръщат към адреса на обработчика. Ако има сесия го пренасочваме обратно към формата. Ако няма сесия и него плюем с "Huston, You have a problem!".
Втората проверка сравнява версията браузъри. Няма равно, пак плюем "Huston, You have a problem!".
Ако до тук е издържано, сравняваме какво получаваме от пресмятането. При неуспех пренасочваме към формата. Всичко започва отначало, като старите променливи се презаписват от само себе си. При успех обработваме информацията. Режем празни символи и сравняваме дължини. Обработката присвояваме на променливи, които предаваме като параметър на функция mail(). Подготовка за писмо един вид. При неуспех с дължините връщаме на изходна позиция.
Функция mail() в моята система Ubuntu 10.04 се обслужва от пощенски трансферен агент Exim4. Той предава на smpt сървър на Google, а от там на посочен от мен електронен адрес. Неща описани в тази тема. Удобно и практично.
При успех/неуспех вадим съобщения и връщаме обратно към формата.
Резултатът няма да влиза в база данни и това обезсмисля функции: addslashes(), mysql_real_escape_string(). Под въпрос е функция htmlspecialchars(). Сървърите обработват спецсимволи, с цел да не допуснат тъпи шеги с писма, съдържащи JS-код. Тук най-вече според случая.
На печелившите честито. На мен браво!
до нови срещи ^.^
0 Response to "Captcha за Web-форма"
Публикуване на коментар