Суть решения
Предложенное решение позволяет при визуальном отсутствии каких-либо раздражающих признаков в пользовательском интерфейсе и незначительном неудобстве для пользователя, сделать малоэффективым массовую рассылку спама через форму размещенную в интернете.
Пример использования
Например, у Вас есть форма обратной связи и вы не хотите её усложнять, например, капчей. Вы уже использовали все доступные способы понять, что с пользовательской стороны точно запущено нечто, похожее на браузер, что в браузере есть JavaScript, что пользователь вводит текст в форму более чем за несколько микросекунд и так далее. Но как бороться со случаем, когда практически все проверки пройдены, а спам есть?
Идея
Применить некоторую ассиметричную операцию, которая будет затратной по ресурсам для клиента и легковесна для проверки с серверной стороны. Другими словами отправка формы должна стать достаточно ресурсоёмкой операцией. Так как с точки зрения обычного польователя «повисание» браузера на 1-3 минуты является не приятной, но вполне приемлемой особенностью работы сайта, а вот для спам бота, если каждай отсылаемая форма будет «съедать» 1-3минуты 100% заргузки одного ядра процессора будет крайне неприятным сюрпризом. Также это позволит бороться со случаями, если спам рассылается именно людьми: т.е. когда и браузер настоящий и есть человек за браузером.
Причем тут Bitcoin?
Из Bitcoin взята идея Proof of work. Другими словами клиентскому браузеру нужно решить головоломку соответствющей сложности, как это делается Bitcoin майнерами: вычислить nonce + hash для некоторого поля формы, причем hash должен отвечать некоторому критерию. Операцию можно решить только перебором, который потребует существенных вычислительных ресурсов для клиента. При этом вычисленное значенеи hash + nonce можно легко проверить на сервере.
JavaScript код на стороне клиента
var isBrowserJsRuntime = (typeof exports === 'undefined'); var nonce; if(isBrowserJsRuntime){ nonce = this['nonce']={}; } else { jsSHA = require('./sha512'); nonce = exports; }; nonce.nonce = function(inString){ var btc = ""; var j = 0; var n = 0; for( ; btc.search('123456') < 0 ; j++ ){ btc = ((new jsSHA( inString + j, 'TEXT')).getHash('SHA-512', 'HEX')); n = j; }; return { 'btc':btc, 'nonce':n }; }; nonce.pushButton = function(thisForm){ var fullMsg = thisForm.message.value; var n = this.nonce(fullMsg); thisForm.btc.value = n.btc; thisForm.nonce.value = n.nonce; thisForm.submit(); };
Дополнительно потреюуется любая JavaScript библиотека вычисляющая любой (ресусоёмкий) hash. Например, отлично подойдет jsSHA, в частности sha512.js
Код работает на node.js (для Unit тестирования) и в браузере Cromium. В качестве критерия подходящего hash применяется последовательность 123456. То есть nonce будет подобран таким образом, чтобы вычисленный hash содержал последовательность ‘123456’.
Perl код на стороне сервера
use Digest::SHA qw(sha512_hex); sub checkProofOfWork($$$){ my $text = shift; my $nonce = shift; my $shaValue = shift; if( $shaValue =~ /123456/ ){ my $digest = sha512_hex( $text . $nonce ); return $digest eq $shaValue; }; return 0; };
Cначала проверяем, что вычисленный hash подходит по критерию и только потом пытаемся пересчитать hash сами.
Заключение
Массовое применение подобного подхода способно существенно усложнить жизнь спамерам.
Также мне интересно мнение сообщества в отношении предложенного подхода и пути его дальнейшего совершенствования.
ссылка на оригинал статьи http://habrahabr.ru/post/207704/
Добавить комментарий