Протокол HTTP предоставляет возможность авторизации пользователя по имени и паролю. Вкратце схема работы выглядит так:
Веб-браузер посылает обычный http-запрос на доступ к запороленному ресурсу на веб-сервере. Пример:
GET / HTTP/1.1 ...
Веб-сервер или веб-приложение формируют http-ответ с кодом 401 и требованием авторизации. Пример basic авторизации:
HTTP/1.0 401 Unauthorized WWW-Authenticate: Basic realm="need authorization" ...
Веб-браузер отображает окно авторизации. Например так:
И после ввода данных посылает второй запрос к веб-ресурсу, содержащий base64-кодированный заголовок Authorization:
GET / HTTP/1.1 Authorization: Basic YWRtaW46c2VjcmV0 ...
Веб-приложение проверяет правильность имени и пароля. Если проверка успешна, выдает нормальный http-ответ:
HTTP/1.0 200 OK ...
Если проверка не успешна, то повторяется http-ответ с кодом 401. При этом в теле http-ответа уже может содержаться дополнительная информация, объясняющая причину отказа.
Про http-авторизацию можно почитать в rfc 2068. Или в русском переводе этого rfc. Механизм http-авторизации не лишен недостатков. Подробно они описаны в статье «Базовая HTTP-авторизация — защита от честных людей» Алексея Мичурина, опубликованной в журнале «Системный администратор» №5 за 2005 г.
Мы рассмотрим использование http-авторизации c perl веб-фреймворком Catalyst. Для Catalyst существует плугин Catalyst::Plugin::Authentication реализующий основу любой авторизации. Но чтобы его использовать нужны ещё два плугина:
Credential — метод получения информации о пользователе. Доступны такие:
- Password — авторизация по логину и паролю полученному, например, через веб-форму.
- HTTP — получение информации о пользователе через http-авторизацию. Именно этим плугином и воспользуемся.
- Прочие.
Store — способ хранения и проверки полученной информации. Возможные хранилища:
- DBIC — хранение информации о пользователях в базе данных, с доступом к ней через ORM, например DBIx::Class.
- Htpasswd — излечение информации из htpasswd файлов, создаваемых одноименной утилитой, входящей в комплект веб-сервера apache. Воспользуемся этим плугином.
- Minimal — данные о пользователях хранятся внутри конфигурации Catalyst-проекта.
- Прочие.
Итак, нам будут нужны следующие установленные perl-модули, естественно, со всеми зависимостями:
- Catalyst::Devel
- Catalyst::Plugin::Authentication
- Catalyst::Plugin::Authentication::Credential::HTTP
- Catalyst::Plugin::Authentication::Store::Htpasswd
Создаем заготовку проекта на фреймворке Catalyst с названием MyApp.
root@darkstar:~# catalyst.pl MyApp created "MyApp" created "MyApp/script" created "MyApp/lib" created "MyApp/root" created "MyApp/root/static" created "MyApp/root/static/images" created "MyApp/t" created "MyApp/lib/MyApp" created "MyApp/lib/MyApp/Model" created "MyApp/lib/MyApp/View" created "MyApp/lib/MyApp/Controller" created "MyApp/myapp.yml" created "MyApp/lib/MyApp.pm" created "MyApp/lib/MyApp/Controller/Root.pm" created "MyApp/README" created "MyApp/Changes" created "MyApp/t/01app.t" created "MyApp/t/02pod.t" created "MyApp/t/03podcoverage.t" created "MyApp/root/static/images/catalyst_logo.png" created "MyApp/root/static/images/btn_120x50_built.png" created "MyApp/root/static/images/btn_120x50_built_shadow.png" created "MyApp/root/static/images/btn_120x50_powered.png" created "MyApp/root/static/images/btn_120x50_powered_shadow.png" created "MyApp/root/static/images/btn_88x31_built.png" created "MyApp/root/static/images/btn_88x31_built_shadow.png" created "MyApp/root/static/images/btn_88x31_powered.png" created "MyApp/root/static/images/btn_88x31_powered_shadow.png" created "MyApp/root/favicon.ico" created "MyApp/Makefile.PL" created "MyApp/script/myapp_cgi.pl" created "MyApp/script/myapp_fastcgi.pl" created "MyApp/script/myapp_server.pl" created "MyApp/script/myapp_test.pl"
Чтобы убедится что всё прошло успешно, запустим проект на встроенном в Catalyst тестовом веб-сервере.
root@darkstar:~# MyApp/script/myapp_server.pl [debug] Debug messages enabled [debug] Loaded plugins: .----------------------------------------------------------------------------. | Catalyst::Plugin::ConfigLoader 0.14 | | Catalyst::Plugin::Static::Simple 0.19 | '----------------------------------------------------------------------------' [debug] Loaded dispatcher "Catalyst::Dispatcher" [debug] Loaded engine "Catalyst::Engine::HTTP" [debug] Found home "/root/MyApp" [debug] Loaded Config "/root/MyApp/myapp.yml" [debug] Loaded components: .-----------------------------------------------------------------+----------. | Class | Type | +-----------------------------------------------------------------+----------+ | MyApp::Controller::Root | instance | '-----------------------------------------------------------------+----------' [debug] Loaded Private actions: .----------------------+--------------------------------------+--------------. | Private | Class | Method | +----------------------+--------------------------------------+--------------+ | /default | MyApp::Controller::Root | default | | /end | MyApp::Controller::Root | end | '----------------------+--------------------------------------+--------------' [info] MyApp powered by Catalyst 5.7007 You can connect to your server at http://darkstar:3000
Как видно, всё замечательно работает. Теперь мы можем обращаться на 3000 порт тестового сервера из браузера и видеть приветственную заставку по умолчанию.
Начинаем прикручивать http-авторизацию. Открываем основной модуль приложения /MyApp/lib/MyApp.pm, находим строчку, отвечающую за загрузку плугинов:
use Catalyst qw/-Debug ConfigLoader Static::Simple/;
И меняем её на:
use Catalyst qw/ -Debug ConfigLoader Static::Simple Authentication Authentication::Store::Htpasswd Authentication::Credential::HTTP /;
Добавляя таким образом загрузку необходимых плугинов авторизации. Теперь изменим файл конфигурации проекта. Открываем /MyApp/myapp.yml и вставляем следующие строчки:
--- name: MyApp authentication: htpasswd: /root/MyApp/myapp.htpasswd http: type: basic
Это файл в странном формате YAML, так что соблюдение всех отступов обязательно. Зато он людьми воспринимается легче чем, например, XML. Желающие изучить вопрос могут начать с последней версии YAML спецификации :-) . Для проверки синтаксиса *.yml файла можно использовать утилиту ysh из perl модуля YAML.pm:
root@darkstar:~# cat MyApp/myapp.yml | ysh $VAR1 = { 'name' => 'MyApp', 'authentication' => { 'htpasswd' => '/root/MyApp/myapp.htpasswd', 'http' => { 'type' => 'basic' } } };
Если проверка завершается успешно, то на выходе видим соответствующую perl структуру данных. Далее создаем htpasswd файл:
root@darkstar:~# htpasswd -c /root/MyApp/myapp.htpasswd admin New password: Re-type new password: Adding password for user admin root@darkstar:~# cat /root/MyApp/myapp.htpasswd admin:mLT84dDiy3H7U
Теперь для авторизированного доступа к определенному action в него достаточно добавить одну строчку кода. Например для доступа ко всем action контроллера Root.pm используем специальный action — auto. Добавим следующие строчки к файлу MyApp/lib/MyApp/Controller/Root.pm:
sub auto : Private { my ( $self, $c ) = @_; $c->authorization_required( realm => 'catalyst http authorization' ); }
Всё, задача выполнена. Опять запускаем тестовый web-сервер:
root@darkstar:~# MyApp/script/myapp_server.pl [debug] Debug messages enabled [debug] Loaded plugins: .----------------------------------------------------------------------------. | Catalyst::Plugin::Authentication 0.10002 | | Catalyst::Plugin::Authentication::Credential::HTTP 0.09 | | Catalyst::Plugin::Authentication::Store::Htpasswd 0.02 | | Catalyst::Plugin::ConfigLoader 0.14 | | Catalyst::Plugin::Static::Simple 0.19 | '----------------------------------------------------------------------------' [debug] Loaded dispatcher "Catalyst::Dispatcher" [debug] Loaded engine "Catalyst::Engine::HTTP" [debug] Found home "/root/MyApp" [debug] Loaded Config "/root/MyApp/myapp.yml" [debug] Loaded components: .-----------------------------------------------------------------+----------. | Class | Type | +-----------------------------------------------------------------+----------+ | MyApp::Controller::Root | instance | '-----------------------------------------------------------------+----------' [debug] Loaded Private actions: .----------------------+--------------------------------------+--------------. | Private | Class | Method | +----------------------+--------------------------------------+--------------+ | /default | MyApp::Controller::Root | default | | /end | MyApp::Controller::Root | end | | /auto | MyApp::Controller::Root | auto | '----------------------+--------------------------------------+--------------' [info] MyApp powered by Catalyst 5.7007 You can connect to your server at http://darkstar:3000
Обратите внимание на лог обработки http-запросов:
[info] *** Request 1 (0.143/s) [5722] [Wed Aug 29 12:52:36 2007] *** [debug] "GET" request for "/" from "172.16.197.1" [debug] Checking http basic authentication. [info] Request took 0.015420s (64.851/s) .----------------------------------------------------------------+-----------. | Action | Time | +----------------------------------------------------------------+-----------+ | /auto | 0.002696s | | /end | 0.000278s | '----------------------------------------------------------------+-----------' [info] *** Request 2 (0.125/s) [5722] [Wed Aug 29 12:52:45 2007] *** [debug] "GET" request for "/" from "172.16.197.1" [debug] Checking http basic authentication. [debug] Successfully authenticated user 'admin'. [info] Request took 0.025378s (39.404/s) .----------------------------------------------------------------+-----------. | Action | Time | +----------------------------------------------------------------+-----------+ | /auto | 0.013852s | | /default | 0.001557s | | /end | 0.000250s | '----------------------------------------------------------------+-----------'
Первый запрос «Request 1» ещё не содержит информации об авторизации. Action обработчик default так и не был выполнен. Запрос «Request 2» уже содержит заполненный http-заголовок Authorization. По этим данным успешно авторизуется пользователь admin. Управление передается action-у, отвечающему за запрошенный урл — default.
Фактически всё программирование свелось к написанию одной строчки кода. Все остальные действия это установка perl-модулей, внесение изменений в существующие конфигурационные файлы и создание новых конфигурационных файлов. Т.е. это действия системного администратора, а не программиста. Это есть одна из основных и моя самая любимая черта веб-фреймворка Catalyst.
3 комментария:
Спасибо за хорошую статью,
только не понял как сам catalyst установить
?
Установил
# apt-get install perl-Catalyst
# apt-get install perl-Catalyst-Devel
# apt-get install perl-Catalyst-Runtime
Но сам
# catalyst.pl
система не находит
:(
Способ корректной установки сильно зависит от вашего дистрибутива linux и используемой там пакетной системы. Пока не назовете название ничего конкретно посоветовать не могу...
В крайнем случае всегда можете воспользоваться установкой perl модулей через cpan.
Дистрибутив ALT Linux 4.0
Но тем не менее я воспользовался вашим советом и установил из CPAN.
Премного благодарен.
:)
Отправить комментарий