Kohana 3.1: Простая аутентификация пользователей

6 апреля 2011 г.

Как многие знают, есть замечательный фреймворк для разработки веб-приложений Kohana. Однако, с выходом новой версии 3.1 были сделаны значительные переработки в работе с фреймворком, и, многие туториалы и мануалы не подходят к новой версии, которая и без того не богата документацией на русском языке.

Целью данной статьи является показать работу с модулем auth в новой версии Kohana 3.1.

Установка

  1. Для начала необходимо скачать последнюю версию с сайта http://kohanaframework.org/
  2. После этого, распаковываем содержимое папки в директорию веб-сервера, который Вы используете.
  3. Запускаем браузер, открываем страницу localhost, или другую, если Вы распаковали куда-то в другое место.
    Смотрим, есть ли ошибки, если есть, исправляем их, а если нет, удаляем или переименовываем install.php
    Проверка на ошибки
  4. Снова открываем нашу страницу и видим 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/',
    ));
    

    Теперь все должно заработать.

    Привет мир!

  5. Пишем приложение

  6. Хочу сказать, что эта статья не предназначена для объяснения сути 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>
    
  7. Теперь нужно создать БД, таблицы и роли.
    Если БД создана, то необходимо выполнить следующий скрипт, который создаст таблицы и роли для работы с 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.

  8. Теперь приступим к настройке приложения.
    Нужно отредактировать /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',
    
  9. После настройки приложения можно переходить к созданию контроллеров.
    Контроллер у нас будет один, выполняющий все функции.
    Я приведу лишь текст контроллера, а объяснения, что он делает будет в комментариях.

    <?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

Вот, в принципе, и все.

Тестируем

  1. Заходим на your_url/member/register, регистрируемся:Регистрация
  2. После этого нас перекидывает на страницу логина, где мы и вводим наши логин/пароль:Логин
  3. После ввода логина/пароля мы попадаем на страницу view:Успешный вход
  4. А после разлогивания нам снова показывают форму ввода логина/пароля:Выход

Заключение

Эта статья была написана, потому что после поиска информации я не нашел нормального руководства по аутентификации пользователей, да еще и на русском языке для версии 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) можно скачать по ссылке.

  • Похожие статьи
  • Предыдущие из рубрики