СтатьиПрограммирование

Система авторизации по переменным окружения.
n0xi0uzz
10 Сентябрь 2006 01:56



Теги: authorisation, perl, environment variables

В данной статье я постараюсь наиболее подробно рассмотреть создание и использование системы авторизации и контроля сессии на основне использования переменных окружения.
Впервые я заинтересовался этой темой благодаря Дмитрию Зернову (так же известному как malgajan) и его разработках в этой области. К сожалению, Дмитрий, в силу некоторых причин, не смог продолжить свою работу в этом направлении, а, по скольку, я использовал подобную систему авторизации в своих проектах, то я волей-неволей начал переписывать те места, которые меня не устраивали, на свой лад.
В итоге, после почти года работы, уже переписав систему с нуля, я имею вполне жизнеспособную и имеющую свои определенные плюсы (и, конечно, минусы) систему авторизации и контроля сессии. Конечно же, она всё ещё требует работы над ней, но работа эта будет далее проводится по некоторым техническим деталям, основные же принципы уже сформулированы и реализованы. Своим опытом по этому поводу я и хотел бы поделиться в этой статье.
Примечание: все примеры по ходу статьи написаны на языке Perl.


Авторизация.
Информация о пользователе (в частности, пароль) хранится на сервере в зашифрованном виде. Для шифрования я использовал стандартную функцию языка Perl crypt(); (как правило, реализующую алгоритм шифрования DES), примерно вот так:
crypt($password, $password);
Где переменная $password — это пароль пользователя. Очевидно, что для этих целей можно использовать любой алгоритм шифрования. Авторизация при этом происходит следующим образом: пользователь заполняет форму на сайте, пароль передаётся в наш скрипт, там он шифруется выбранным нам алгоритмом и сравнивается с тем, что мы храним на сервере. Думаю, не надо упоминать здесь то, что пароль, передаваемый пользователем и пароль, хранящийся на сервере должен быть зашифрован одним и тем же алгоритмом.
Если пароль корректен, то мы начинаем формировать данные для ведения сессии. Вообще говоря, сама сессия нужна для того, чтобы пользователь не вводил пароль на каждой странице для доступа к информации, а информация о нём передавалась вместе с ним. В данной системе это реализовано за счет использования дополнительного CGI-параметра, который мы назовем хешем, добавляемого к каждой ссылке. Таким образом, мы переходим к следующему пункту статьи.


Контроль сессии.
Итак, нам необходимо сформировать информацию о пользователе, которая будет передаваться вместе с ним и подтверждать факт авторизации. Очевидно, что надо предусмотреть все попытки несанкционированного доступа, то есть быть увереным в том, что хеш, используемый пользователем, корректен и используется именно тем пользователем, к которому данный хеш был "привязан". Кроме того, для большей безопасности, был реализован таймаут сессии, то есть если хешем пользователь не пользуется больше определенного количества времени, хеш просто-напросто удаляется.
Формировать хеш, удовлетворяющий всем вышеуказанным условиям, мы будем, основываясь на трех переменных окружения, — REMOTE_ADDR, HTTP_USER_AGENT, HTTP_X_FORWARDED_FOR (IP-адрес пользователя, информация о браузере пользователя и данные передачи прокси-сервера, соответственно). Также, для полной надежности, мы сгенерируем случайное целое число в интервале от 0 до 99 и "привяжем" его к данной сессии.
Формирование хеша происходит достаточно просто, — сначала считается "контрольная сумма", а именно: считается сумма номеров символов каждой переменной. Вот пример кода:
@ENVs = ($ENV{"REMOTE_ADDR"}, $ENV{"HTTP_USER_AGENT"}, $ENV{"HTTP_X_FORWARDED_FOR"});
foreach $item (@ENVs)
{
    foreach ((split(//, $item))) {$hash += ord(($_));};
}
В итоге, в переменной $hash мы получаем вышеуказанную сумму. Затем проделываются следующие действия: генерируется случайное число и, используя всё туже функцию crypt(); (или более удобный для вас способ шифрования), "контрольная сумма" шифруется по случайному числу. Для того, чтобы хеш не получился слишком длинным и имел фиксированную длину для всех пользователей, полученный предыдущим действием хеш, "обрезается" до указанной длины. Далее — пример кода:
$id = int(rand(99));
$hash = substr(crypt($hash, $id), 2, 8);
Важно заметить, что и хеш, и случайно сгенерированное число (и, может быть, другую информацию о пользователе, например, уровень доступа или его имя/логин), необходимо хранить на сервере для последующей проверки корректности данных сессии. Также, необходимо сохранить и время авторизации на сервере для осуществления таймаута сессии. Я для этого использовал стандартную функцию time();.
Полученный хеш, как уже было сказано выше, добавляется CGI-параметром к каждой ссылке на сайте, предлагаемой пользователю. Каждый раз, когда пользователь хочет получить доступ к защищенной информации, мы будем проверять его хеш. Делается это так: точно таким же образом формируется ещё раз хеш, за исключением только того, что при авторизации мы генерировали случайное число, а сейчас мы будем использовать число, хранимое на сервере и "привязанное" к хешу; и сравнивается с исходным. Затем, вычисляется время проверки сессии и сравнивается с временем предыдущей проверки (или же, авторизации). Если полученный хеш совпадает с исходным, необходимо обновить иноформацию о сессии, банально изменив время проверки на сервере. Если же вышеописанные условия не соблюдаются, сессию необходимо завершить, удалив всю информацию о ней на сервере и, желательно, переадресовав пользователя.


Плюсы и минусы.
Как и всё окружающее нас (а особенно, в мире информационных технологий), данная система авторизации и контроля сессии имеет свои плюсы и минусы. Я не буду долго останавливаться на этом, так как не вижу в этом никакого смысла, выделю лишь два основных момента, причем один вытекает из другого:
"+" В отличие от авторизации и контроля сессии на основе использования технологии cookies, пользователь не хранит никакой информации на своем компьютере, что исключает опасность уязвимого пользователя.
"-" Нет "запоминания" пользователя, что означает то, что пользователю необходимо авторизироваться каждый раз, как только истечет таймаут сессии.
Также рекомендую для шифрования паролей использовать более стойкие алгоритмы шифрования. Например, Blowfish.


Ссылки по теме.
Пример системы web-аутентификации Дмитрий Зернов aka malgajan
Список основных переменных окружения и небольшие комментарии.
Coogle


© Черкасов Виктор aka n0xi0uzz, 2006


Теги: authorisation, perl, environment variables

Статьи с такими же тегами:

Гостевая книга на perl: последние штрихи.
Клиент для LiveJournal.com на Perl
Обработка PDF на Perl.
Использование AJAX в Perl.
Выбирая шаблонизатор на Perl.