18 мая 2008 г.

Аутентификация, авторизация, учёт и аудит используя Memcached

Memcached - система распределённого хранения данных в оперативной памяти, изначально разработанная для сервиса LiveJournal.com. Основные преимущества системы включают в себя: значительное уменьшение нагрузки на реляционные базы данных, и лёгко-масштабируемую систему.
Процессы аутентификации, авторизации, учёта и аудита, сейчас необходимы для работы большинства веб-приложений, но в тоже время классические схемы реализации, создают высокую нагрузку на RDBM, либо для её уменьшения затрат часть функций либо исключается, либо переносится, на автономно работающие модули, как правило это аудит.

Модуль Apache2::AuthCookie позволяет на уровне событий веб-сервера Apache, осуществлять авторизацию и аутентификацию пользователей, аудит осуществляется стандартными средствами Apache, например:

192.168.1.4 - wise [18/May/2008:18:16:38 +0600] "GET /favicon.ico HTTP/1.1" 404 277
192.168.1.4 - wise [18/May/2008:18:16:39 +0600] "GET /files?start=6 HTTP/1.1" 200 5760
192.168.1.4 - - [18/May/2008:18:16:39 +0600] "GET /ru/css/main.css HTTP/1.1" 200 5096
192.168.1.4 - wise [18/May/2008:18:16:39 +0600] "GET /favicon.ico HTTP/1.1" 404 277
192.168.1.4 - wise [18/May/2008:18:16:40 +0600] "GET /files?start=1 HTTP/1.1" 200 7528
192.168.1.4 - - [18/May/2008:18:16:41 +0600] "GET /ru/css/main.css HTTP/1.1" 200 5096
в последствии делая анализ логов. Учет в большинстве случаем, если он необходим, просто осуществлять на уровне авторизации.

Учётные записи в моем примере реализации хранятся в БД PostgreSQL, небольшой модуль для работы с Memcached базирующийся на модуле Apache2::AuthCookie, выполняет аутентификацию, использую БД, генерацию ключа сессии, получение из БД специфических для пользователя переменных, необходимых для работы сессии, но являющимися данными для временного характера, и помещение их в массив памяти с ключам сессии.
Авторизация осуществляется путём проверки наличия наличия данных на любом сервере memcached. Что по сути являются достаточно быстрой операцией, что очень важно, потому-что авторизацию необходимо осуществляет при любом запросе пользователя.
Таким образом, за все время работы пользователя, запросы к БД осуществляются всего один раз.

Хранение определённых параметров пользователя не требует как правило больших затрат памяти на одного пользователя, и зависит только от организации данных, у меня это максимум 1Кб. Но при необходимости эту цифру можно увеличивать, вопрос только в количестве физической памяти выделяемой, на реализацию, при этом желательно учест тот факт что клиент memcached выполняет асинхронные запросы, поэтому поиск на двух серверах с 2Gb памяти, будет выполнятся быстрей, чем на одном 4Gb.
При этом выделять для не идентифицированных пользователей, выделять память необходимости нет. И расчёт требуемого объёма памяти определяется из пикового количества одновременно находящихся на сервере пользователей.

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

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

8 мая 2008 г.

Imagination - сложно человеку, легко машине



Несколько слов об Imagination от ALIPR ™, и о методе прохода данной вариации теста Тьюринга.

Красные круги - это место кликнув на которое я прохожу тест, я беру случайную точку в зеленом прямоугольнике, потомучто центр картинки будет на краю в очень редком случае, на этом рисунке есть но не весь. Хотя размер области можно и увеличить.
Имитирую запрос к серверу, сервер говорит попал ли я или нет, если не попал то беру другую точку, опять же картинка не удаляется после неверного ввода, но всегда можно скачать новую(результат будет тот же).
Области красных кругов кажутся маленькими, потомучто я не знаю радиус валидного клика, меньше 10 он быть не может человеку попасть просто не реально, я нарисовал 50, но тесты показали что это значение больше. Можно конечно же дополнительно исключить центр прямоугольника и увеличить вероятность попадания до 30-40% , но это уже больше тюнинг, пока имеет значения только принцип, да и к томуже текуший вариант на сайте alipr, тестовый и не окончательно завершен.
Результаты количество запросов для прохождения: 1/18/30 min/avg/max.
Метод тупого перебора практически не требует процессорных ресурсов, на какое либо опознание, он требует только хороший канал связи, на 128Кб, бот проходит оба теста за 2-5 секунды, но ведь всегда можно написать многопоточный ассинхронный скрипт.
Автор утверждает что усилит защиту теста, проверками на неверный клик, увеличинием числа шагов прохождения, но в любом случае эти дополнительные меры защиты можно было бы добавить и на обычную капчу, и капча в которой всего две цифры, больше защишена от перебора, легче воспринимается настоящими людьми, чем два, три или даже четыре, подряд идуших теста с постоянно меняющейся логикой, интересно много ли администраторов, согласятся сделать подобную онлайн-игру-квест, для своих пользователей.

Да и к тому-же до сих пор нет решения позволяющего обойти метот привлечения большого количества стороних пользователей(обманным путем, или даже за плату), для прохождения тестов Тьюринга основаных на CAPTCHA.

Пример кода который проходит оба теста.


#!/usr/bin/perl -w
#(c) Alego;
use strict;
use LWP;

my $server="http://www.alipr.com/captcha/";

my $ua = LWP::UserAgent->new;
$ua->agent("Hey humans! I am a bot, and I am pass u tests");

my $res = $ua->get($server);
my @array=split(/\n/, $res->content);
my $str;
my $picture;
foreach $str (@array){
if ($str=~m/img1.src[^"]*\"([^"]*)\"/){
$picture=$1;
print "Picture path: $1\n";
last;
}
}

my $x;
my $y;
my $status=undef;
my $counter=0;
while (not $status){
$counter++;
#center any image could't be in border;
$x = 100 + int rand 600;
$y = 100 + int rand 400;
$res = $ua->post("$server"."process.php", , [x =>; $x , y=>; $y,debug =>; 'false', source=>'image_center', img=>$picture], 'referer'=>$server);
if (not $res->header('Location')=~m/fail/){
print $x."x".$y;
print " - Found ($counter)\n";
last;
}
}

#second test

$res = $ua->get($server."index2.php");
@array=split(/\n/, $res->content);

foreach $str (@array){
if ($str=~m/img1.src[^"]*\"([^"]*)\"/){
$picture=$1;
print "Distorted picture path: $1\n";
last;
}
}
my $content;
for ($counter=1;$counter<16;$counter++){
$content=$counter;
$res = $ua->post("$server"."process.php", , [source => 'false', source=>'image_content', img=>$picture,content=>$content], 'referer'=>$server);
if (not $res->header('Location')=~m/fail/){
print $content;
print " - Found ($counter)\n";
last;
}
}

print "\n";

1;


Результаты выполнения:

Picture path: outfiles/tile_pic_12101687605768.jpg
337x403 - Found (2)
Distorted picture path: outfiles/distorted_pic_12101687645770.jpg
1 - Found (1)

Picture path: outfiles/tile_pic_12101687707474.jpg
355x214 - Found (8)
Distorted picture path: outfiles/distorted_pic_12101687768265.jpg
15 - Found (15)

Picture path: outfiles/tile_pic_12101687902300.jpg
482x380 - Found (4)
Distorted picture path: outfiles/distorted_pic_12101687947397.jpg
3 - Found (3)

Picture path: outfiles/tile_pic_12101688015580.jpg
675x338 - Found (1)
Distorted picture path: outfiles/distorted_pic_12101688052686.jpg
10 - Found (10)

Picture path: outfiles/tile_pic_12101693022674.jpg
404x153 - Found (5)
Distorted picture path: outfiles/distorted_pic_12101693077510.jpg
14 - Found (14)

Picture path: outfiles/tile_pic_12101693352794.jpg
420x463 - Found (1)
Distorted picture path: outfiles/distorted_pic_12101693385386.jpg
11 - Found (11)