Протокол 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. |