Секретные web-материалы
Евгений ФИДЕЛИН Евгений
ФИДЕЛИН
Тема этой статьи может сперва показаться
странной: действительно, ведь основным (я бы сказал,
ежедневным :-)) занятием web-мастера является увеличение
трафика, а в данном материале рассмотрен вопрос, как ограничить
доступ к вашим страницам, т.е. уменьшить этот самый трафик. Однако,
исходя из своего личного опыта, хочу сказать, что очень часто это
бывает необходимо.
Зачем?
Представим себе, что вы создали какой-нибудь интерактивный
интернет-сервис (онлайн-тест, обучалку, игру и т.д.
и т.п.), причем за свою работу, как любой нормальный человек,
хотите получить деньги. Для этого нужно сделать элементарную защиту,
чтобы пользователь, который не знает логина и пароля, не мог
воспользоваться результатом вашего труда (а на продаже этих самых
логинов и паролей вы и заработаете деньги).
Или еще один пример: у вас есть важный документ, который вам
очень часто необходим - загружаете его к себе на сайт, и он
будет доступен вам всегда и везде, где есть Интернет. Теперь
осталось защитить его от посторонних глаз, и все.
Как?
Тут возникают три различных варианта, давайте их обсудим.
Вариант первый - использование CGI-программ. Чем этот
вариант плох, так это тем, что не все хостинги, а в особенности
бесплатные, предоставляют такую возможность (см. статьи Ольги
КАЛИТКИ <Приют для сайта>, МК №27 (250), и
<Сайт-квартиросъемщик>, МК №29 (252)), к тому же написание
таких программ - дело очень сложное или дорогое, уж кому как.
Вариант второй - использование PHP, SSI и
прочих им подобных. Опять-таки, не все хостинги поддерживают такую
возможность, хотя написание на них программы (скрипта, сценария) не
составляет больших трудностей.
Вариант третий и последний - использование
JavaScript. Не требуется никаких поддержек со стороны
сервера, т.к. все выполняет сам браузер, к тому же язык JavaScript
очень легок в использовании, хотя и ограничен в возможностях. Здесь
я сознательно не упоминаю VBScript, т.к. он менее
распространен и не обладает теми средствами, которые доступны в
JavaScript (см. статьи Константина НОСОВА , МК №№20, 23, 29 (243, 246, 252)).
Если вы (как, впрочем, и я :-)) остановили свой выбор на
третьем варианте, то продолжайте читать дальше; остальным тоже
советую присоединиться - будет интересно.
Теория
Для начала давайте вы мысленно (а я - письменно) представите
механизм нашей многопользовательской защиты.
Пусть в папке находятся страница с формой запроса логина и пароля
(Рис. 1), страницы с именами [логин][пароль].htm (для
каждого пользователя своя) и <секретная> страница.
Идея довольно проста - пользователь вводит логин и пароль,
сценарий JavaScript загружает страницу [логин][пароль].htm, которая
в свою очередь автоматически заменяется <секретной> страницей.
Это все произойдет, если пользователь укажет правильный логин и
пароль. А если нет? Произойдет попытка открыть несуществующий файл
[логин][пароль].htm, что вызовет сообщение об ошибке 404 Not
Found. Это не столь ужасно, однако пользователь не поймет, то ли
это он ошибся при вводе, то ли это проблема работы сервера. Также
есть вероятность того, что файл с именем [логин][пароль].htm реально
существует, однако никак не связан с <секретной> страницей -
тогда загрузка этой страницы в браузер может вызвать у пользователя
замешательство.
Из-за соображений безопасности язык JavaScript лишен каких бы-то
ни было функций для работы с файлами, поэтому узнать, существует
файл [логин][пароль].htm либо нет, нам не удастся. Однако из этого
вовсе не следует, что нам придется смириться с таким положением
вещей - мы применим одну хитрость!
Хитрость заключается в том, что у объекта img (изображение) есть
событие Error, которое возникает, когда происходит попытка загрузить
несуществующую картинку. Этим-то мы и воспользуемся - создадим
для каждого файла [логин][пароль].htm свою картинку
[логин][пароль].htm и, перед тем как загрузить страницу, будем
загружать соответствующий ему файл изображения. Если при этом
возникнет событие Error (т.е. картинки попросту нет), то загружать
страницу мы не будем, а выдадим сообщение об ошибке
(Рис. 2). Реализовав эту систему, мы получим возможность
лишать пользователя доступа к странице, просто удалив необходимое
изображение.
>
Аналогичную защиту необходимо внедрить и в саму <секретную>
страницу, чтобы нельзя было получить к ней доступ, введя ее имя в
адресной строке. Для этого мы будем передавать ей параметр -
строку [логин][пароль]; если этот параметр окажется неверен, то
пользователь автоматически перейдет на страницу с формой запроса.
Ну вот, с теорией вроде бы разобрались, пора двигаться дальше.
Практика
Ниже приведены три листинга: для личной страницы пользователя,
<секретной> страницы и страницы с формой запроса логина и пароля.
Все они сопровождаются подробными комментариями, так что с
пониманием проблем возникнуть не должно. Единственное, о чем я
жалею, - нельзя на страницах журнала устроить <подсветку
синтаксиса>, а то ведь как бы было здорово, да и понятнее.
Тексты личных страниц пользователей имеют одинаковую структуру
(см. листинг ниже), отличаются они только именами (для начала
создайте хотя бы два таких файла с именами login1password1.htm и
login2password2.htm).
Здесь для перехода на новую страницу мы использовали метод
location.replace(), чтобы промежуточная страница не заносилась в
журнал браузера, и на нее нельзя было вернуться, нажав кнопку
<Назад>. Если вы будете использовать данную защиту у себя на сайте,
то замените secret.htm на имя своей страницы, а login1password1 на
соответствующую строку [логин][пароль], которая совпадает с именем
личной страницы пользователя.
В тексте <секретной> страницы обязательно должен присутствовать
следующий фрагмент:
Здесь мы описали две функции: test_filename() выполняется сразу
при загрузке страницы, проверяет верность переданного параметра и
выводит сообщение (Рис. 3), а go_back(), если параметр
неверен, отсылает пользователя к странице index.htm.
А вот листинг страницы с формой запроса логина и пароля:
В данном листинге описано три функции:
функция check_password() обрабатывает клик на кнопке <Вход> и
служит для определения истинности введенных логина и пароля;
функция test_password() обрабатывает загрузку изображения и, если
пароль и логин верны, направляет пользователя на страницу
[логин][пароль].htm.
и наконец, последняя функция password_error() служит для
обработки события onError объекта img.
Если вы будете использовать приведенные выше листинги, то
обратите внимание на строчные и прописные буквы - JavaScript
чувствителен к регистру.
Советы
Чтобы наша защита работала надежно и быстро, необходимо учесть
еще несколько нюансов:
в папке вместе с файлами [логин][пароль].htm и <секретной>
страницей обязательно должна находится стандартная страница с именем
index.htm или index.html (это может быть страница с формой запроса).
Она необходима для того, чтобы пользователь, введя только имя
каталога, не мог получить список всех файлов, находящихся в
нем - вместо этого будет отображена стандартная страница;
если вы собираетесь хранить на сайте ну очень уж важную
информацию :-), то существует вероятность того, что опытный
пользователь, используя CGI-программу, сможет получить доступ к
файлам каталога. Для предотвращения подобных попыток взлома на
сервере под управлением UNIX необходимо изменить разрешение для
каталога, запретив доступ к нему с помощью CGI-программ. Это можно
сделать средствами FTP-клиента;
объем используемых файлов изображений должен быть как можно
меньшим - идеальный размер - 11 пиксель. К тому же
изображение должно быть прозрачным; для этого надо использовать
формат .gif;
если у вас нет специальных программ для отладки сценариев
JavaScript, советую пользоваться стандартными средствами браузера
Netscape Navigator. Чтобы доступиться к консоли JavaScript
(Рис. 4), просто наберите в адресной строке
javascript:.
Итого
Мы получили легкую в реализации и надежную в работе
многопользовательскую защиту для вашей <секретной> страницы,
работающую в таких браузерах как Internet Explorer 4 и выше,
Netscape Navigator 4.5 и выше, Opera 6 и выше. Чтобы
проверить ее в действии, загляните на мой сайт по адресу http://www.abyss-group.narod.ru/docs/articles/test,
данные для доступа: login1, password1 и login2, password2.
|