Kohana 3.1: Простая аутентификация пользователей
Как многие знают, есть замечательный фреймворк для разработки веб-приложений Kohana. Однако, с выходом новой версии 3.1 были сделаны значительные переработки в работе с фреймворком, и, многие туториалы и мануалы не подходят к новой версии, которая и без того не богата документацией на русском языке.
Целью данной статьи является показать работу с модулем auth в новой версии Kohana 3.1.
Установка
- Для начала необходимо скачать последнюю версию с сайта http://kohanaframework.org/
- После этого, распаковываем содержимое папки в директорию веб-сервера, который Вы используете.
- Запускаем браузер, открываем страницу localhost, или другую, если Вы распаковали куда-то в другое место.
Смотрим, есть ли ошибки, если есть, исправляем их, а если нет, удаляем или переименовываем install.php
- Снова открываем нашу страницу и видим Hello, world!
Важно! Если вместо этого Вы видите ошибку:
То это значит, что Вам еще нужно настроить .htaccess. В стандартной поставке уже идет example.htaccess, его нужно переименовать в .htaccess и изменить.
В моем случае мне достаточно изменить строчку
RewriteBase /
на
RewriteBase /kohana/
Также, не стоит забывать, что обработка файла .htaccess должна быть у Вас включена.
Помимо этого, необходимо изменить значение в /application/bootstrap.php
с такого:Kohana::init(array( 'base_url' => '/', ));
на такое, где /kohana/ это ваш URL
Kohana::init(array( 'base_url' => '/kohana/', ));
Теперь все должно заработать.
- Хочу сказать, что эта статья не предназначена для объяснения сути MVC фреймворков в целом, а лишь объясняет работу в Kohana auth . Поэтому, сразу приступим к созданию видов (представлений|view).
Нам понадобятся два: 1) для логина 2) для регистрации пользователей.
Создадим /application/views/login.php с таким содержанием:<form method="post" accept-charset="utf-8"> <label for="username">Username:</label> <input id="username" type="text" name="username" /> <br /> <label for="password">Password:</label> <input id="password" type="password" name="password" /> <br /> <button type="submit">Login</button> </form>
/application/views/register.php с таким содержанием:
<form method="post" accept-charset="utf-8"> <label for="username">Username:</label> <input id="username" type="text" name="username" /> <br /> <label for="email">Email:</label> <input id="email" type="text" name="email" /> <br /> <label for="password">Password:</label> <input id="password" type="password" name="password" /> <br /> <label for="password_confirm">Repeat Password:</label> <input id="password_confirm" type="password" name="password_confirm" /> <br /> <button type="submit">Register</button> </form>
- Теперь нужно создать БД, таблицы и роли.
Если БД создана, то необходимо выполнить следующий скрипт, который создаст таблицы и роли для работы с Auth:CREATE TABLE IF NOT EXISTS `roles` ( `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `description` varchar(255) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uniq_name` (`name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; INSERT INTO `roles` (`id`, `name`, `description`) VALUES(1, 'login', 'Login privileges, granted after account confirmation'); INSERT INTO `roles` (`id`, `name`, `description`) VALUES(2, 'admin', 'Administrative user, has access to everything.'); CREATE TABLE IF NOT EXISTS `roles_users` ( `user_id` int(10) UNSIGNED NOT NULL, `role_id` int(10) UNSIGNED NOT NULL, PRIMARY KEY (`user_id`,`role_id`), KEY `fk_role_id` (`role_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `users` ( `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, `email` varchar(127) NOT NULL, `username` varchar(32) NOT NULL DEFAULT '', `password` char(64) NOT NULL, `logins` int(10) UNSIGNED NOT NULL DEFAULT '0', `last_login` int(10) UNSIGNED, PRIMARY KEY (`id`), UNIQUE KEY `uniq_username` (`username`), UNIQUE KEY `uniq_email` (`email`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE IF NOT EXISTS `user_tokens` ( `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT, `user_id` int(11) UNSIGNED NOT NULL, `user_agent` varchar(40) NOT NULL, `token` varchar(32) NOT NULL, `created` int(10) UNSIGNED NOT NULL, `expires` int(10) UNSIGNED NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `uniq_token` (`token`), KEY `fk_user_id` (`user_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; ALTER TABLE `roles_users` ADD CONSTRAINT `roles_users_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, ADD CONSTRAINT `roles_users_ibfk_2` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE; ALTER TABLE `user_tokens` ADD CONSTRAINT `user_tokens_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE;
Это, собственно, стандартный скрипт из http://docs.kohanaphp.com/addons/auth#mysql_schema, но с незначительным изменением, в виде длины пароля. Теперь это 64 символа вместо 50.
- Теперь приступим к настройке приложения.
Нужно отредактировать /application/bootstrap.php, указав, что мы хотим использовать модули database, orm и auth:Kohana::modules(array( 'auth' => MODPATH.'auth', // Basic authentication // 'cache' => MODPATH.'cache', // Caching with multiple backends // 'codebench' => MODPATH.'codebench', // Benchmarking tool 'database' => MODPATH.'database', // Database access // 'image' => MODPATH.'image', // Image manipulation 'orm' => MODPATH.'orm', // Object Relationship Mapping // 'unittest' => MODPATH.'unittest', // Unit testing // 'userguide' => MODPATH.'userguide', // User guide and API documentation ));
Скопируйте в /application/config/ два файла:
/modules/database/config/database.php
/modules/auth/config/auth.php
Теперь нужно изменить /application/config/database.php таким образом:'hostname' => 'localhost', 'database' => 'Ваша_база', 'username' => 'Пользователь', 'password' => 'Пароль',
А /application/config/auth.php таким образом:
'driver' => 'orm', 'hash_method' => 'sha256', 'hash_key' => 'Здесь_нужно_написать_ключ_хэша', 'lifetime' => 1209600, 'session_key' => 'auth_user',
- После настройки приложения можно переходить к созданию контроллеров.
Контроллер у нас будет один, выполняющий все функции.
Я приведу лишь текст контроллера, а объяснения, что он делает будет в комментариях.<?php defined('SYSPATH') or die('No direct access allowed.'); // Описание класса class Controller_Member extends Controller { public function action_index() { // Тут можно сделать ссылки на вход и регистрацию echo 'Hello, world!'; } // Регистрация пользователей public function action_register() { // Если есть данные, присланные методом POST if ($_POST) { // Создаем переменную, отвечающую за связь с моделью данных User $model = ORM::factory('user'); // Вносим в эту переменную значения, переданные из POST $model->values(array( 'username' => $_POST['username'], 'email' => $_POST['email'], 'password' => $_POST['password'], 'password_confirm' => $_POST['password_confirm'], )); try { // Пытаемся сохранить пользователя (то есть, добавить в базу) $model->save(); // Назначаем ему роли $model->add('roles', ORM::factory('role')->where('name', '=', 'login')->find()); // И отправляем его на страницу пользователя $this->request->redirect('member/view/'); } catch (ORM_Validation_Exception $e) { // Это если возникли какие-то ошибки echo $e; } } // Загрузка формы логина $this->response->body(View::factory('register')); } // Просмотр пользовательских данных public function action_view() { // Проверям, залогинен ли пользователь if(Auth::instance()->logged_in()) { // Если да, то здороваемся и предлагаем выйти. Это можно было и в виде view реализовать echo 'Добро пожаловать, '.Auth::instance()->get_user()->username.'!'; echo '<br /><a href=\'logout\'>logout</a>'; } else { // А если он не залогинен, отправляем логиниться return $this->request->redirect('member/login'); } } // Метод разлогивания public function action_logout() { // Пытаемся разлогиниться if (Auth::instance()->logout()) { // Если получается, то предлагаем снова залогиниться return $this->request->redirect('member/login'); } else { // А иначе - пишем что не удалось echo 'fail logout'; } } // Метод логина public function action_login() { // Проверям, вдруг пользователь уже зашел if(Auth::instance()->logged_in()) { // И если это так, то отправляем его сразу на страницу пользователей return $this->request->redirect('member/view'); } // Если же пользователь не зашел, но данные на страницу пришли, то: if ($_POST) { // Создаем переменную, отвечающую за связь с моделью данных User $user = ORM::factory('user'); // в $status помещаем результат функции login $status = Auth::instance()->login($_POST['username'], $_POST['password']); // Если логин успешен, то if ($status) { // Отправляем пользователя на его страницу $this->request->redirect('member/view'); } else { // Иначе ничего не получилось, пишем failed echo 'failed'; } } // Грузим view логина $this->response->body(View::factory('login')); } }
Этот контроллер нужно создать в файле /application/classes/controller/member.php
Пишем приложение
Вот, в принципе, и все.
Тестируем
- Заходим на your_url/member/register, регистрируемся:
- После этого нас перекидывает на страницу логина, где мы и вводим наши логин/пароль:
- После ввода логина/пароля мы попадаем на страницу view:
- А после разлогивания нам снова показывают форму ввода логина/пароля:
Заключение
Эта статья была написана, потому что после поиска информации я не нашел нормального руководства по аутентификации пользователей, да еще и на русском языке для версии Kohana 3.1. Я разобрался самостоятельно, использовав следующие источники, в том числе и для написания статьи:
http://blog.mixu.net/2010/09/06/step-by-step-guide-to-kohana-3-auth/ — Статья по использованию useradmin;
http://forum.kohanaframework.org/ — Форум, где много полезной информации;
http://kerkness.ca/wiki/doku.php — Неофициальное wiki.
Полностью проект (но без настроек БД и настроек модуля auth) можно скачать по ссылке.