Nginx-ru mailing list archive (nginx-ru@sysoev.ru)
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: nginx+captcha
Набросал прототип с использованием встроенного perl
(если бы этот патчик
http://catap.ru/blog/2009/05/13/nginx-crc32_name-and-md5_name/ позволял
собирать 0.8.40, то перл был бы не нужен вовсе)
Работает оно так - новый юзер редиректится на страничку с капчой test.html,
капча в ней берется через ngx_random_index_module из папки с набором картинок и
одновременно юзеру отправляется кука, вычисляемая как
crc32($captcha_content.$remote_addr)
Картинки капчи заранее разгаданы и называются сответственно своему содержимому,
например ki1q2.png ;)
Человек вводит капчу и по кнопке "отправить" его вариант GET-ом летит на сервер
в виде запроса /rcaptcha/?input=blabla
Там производится сравнение куки ct и присланного инпута и в случае успеха
выдаётся кука ha, которая считается как crc32('secret word'.$remote_addr), или,
если капча введена неверно, делается редирект обратно на test.html.
С $cookie_ha нашему юзеру теперь везде есть ход.
Таким образом никаких данных на сервере не хранится, и для проверки
правильности ввода капчи нужно производить лишь сравнительно быстрые вычисления
crc32.
Можно было сделать всё это в виде одного перломодуля, но не случилось. Текущий
вариант несколько неизящен из-за дублирования кода в определениях переменных,
но зато весьма быстр ( 550Мбит/c трафика через ab с 50000r/s, LA на сервере
поднялся лишь до 4-х ).
[code]
http {
...
perl_set $crc32_ct '
sub {
use String::CRC32;
my $r = shift;
my $ct=$r->uri;
$ct=~ s/.*\/captchas\/(.+)\.png/$1/g;
return crc32($ct.$r->remote_addr);
}';
perl_set $check_input '
sub {
use String::CRC32;
my $r = shift;
my $input=$r->args;
$input=~ s/.*input=(.+)/$1/g;
my $cookie_ct=$r->header_in("Cookie");
$cookie_ct=~ s/.+ct=([^\ ]+).*/$1/g;
if ( $cookie_ct == crc32($input.$r->remote_addr) ) { return 1; } else
{return 0;}
#return crc32($ct.$r->remote_addr);
}';
perl_set $crc32_ha '
sub {
use String::CRC32;
my $r = shift;
return crc32($r->remote_addr."secret word");
}';
perl_set $check_ha '
sub {
use String::CRC32;
my $r = shift;
my $cookie_ha=$r->header_in("Cookie");
$cookie_ha=~ s/.+ha=([^\ ]+).*/$1/g;
#if ( !$cookie_ha ) return 0;
if ( crc32($r->remote_addr."secret word") == $cookie_ha ) { return 1; }
else {return 0;}
}';
server {
listen 80;
server_name test;
root /opt/www/test;
location /test.html {
if ( $fu ) {
add_header Set-Cookie "fu=$fu; path=/";
}
}
location / {
if ( $check_ha = "0" ) { # Если нет волшебной куки, выставляемой
после верного ввода капчи, или она неверна - редирект.
set $fu "$request_uri";
rewrite ^ /test.html;
}
}
location /captchas/ { # В папке captchas лежат капчи в виде картинок,
имя файла равно содержимому ;)
random_index on;
add_header Set-Cookie "ct=$crc32_ct; path=/";
}
location /rcaptcha/ { # Сюда прилетают попытки отгадать капчу
if ( $check_input ) { # Если всё верно - выставляем волшебную куку
ha, по которой везде пускают
add_header Set-Cookie "ha=$crc32_ha; path=/";
rewrite ^ $cookie_fu redirect; # И делаем редирект на
изначально запрошенную юзером страницу.
}
rewrite ^ /test.html redirect; # Неверно - обратно на капчу.
}
error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location ~ /(50x|404).html {
root html;
}
}
}
[/code]
Содержимое файла test.html:
[code]
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<title>Капча</title>
<style type="text/css">
* { font-size: 100.01%; }
body { background: #fff; font-size: 0.8em; }
div { margin-top: 1em; font: 175% Arial, sans-serif; }
</style>
</head>
<body>
<table border="0" width="100%" style="height: 100%">
<tr><td align="center"><img src="/captchas/" border="0" alt="Captcha"/>
<form name="test" method="get" action="/rcaptcha/">
<p><b>Введите символы, изображенные на картинке:</b><br>
<input name="input" type="text" size="6">
</p>
<p><input type="submit" value="Отправить">
<input type="reset" value="Очистить"></p>
</form>
</td></tr></table></body></html>
[/code]
Мотивированная критика и анализ возможностей обойти капчу всячески
приветствуются ;)
Posted at Nginx Forum: http://forum.nginx.org/read.php?21,95997,98028#msg-98028
_______________________________________________
nginx-ru mailing list
nginx-ru@xxxxxxxxx
http://nginx.org/mailman/listinfo/nginx-ru
|