Модуль AUTH в Kohana

kohana Тема где-то баянистая, где-то подробно описанная, но почему-то мне таки пришлось нарабатывать свой опыт и набивать свои шишки. Итак я публикую свой опыт работы с модулем Auth фреймворка Kohana.

Включаем и настраиваем
———————————————
Сначала нужно включить использование модуля в файле application/bootstrap.php. Кроме модуля auth нам понадобятся модули Database и ORM, так что их тоже нужно включить, если они ещё не включены.

Kohana::modules(array(
	'auth'       => MODPATH.'auth',       // Basic authentication
	// 'codebench'  => MODPATH.'codebench',  // Benchmarking tool
	 'database'   => MODPATH.'database',   // Database access
	// 'image'      => MODPATH.'image',      // Image manipulation
	 'orm'        => MODPATH.'orm',        // Object Relationship Mapping
	// 'pagination' => MODPATH.'pagination', // Paging of results
	// 'userguide'  => MODPATH.'userguide',  // User guide and API documentation
	));

Потом заходим в modules/auth/config/auth.php и вносим свои настройки
Перечислю самые интересные настройки:

  • driver — Драйвер данных. Может быть ORM или file. Файловый вариант у меня запустить не получилось. То ли я что-то не так делал, то ли драйвер сырой. Так что используйте ORM :)
  • hash_method — метод хеширования
  • salt_pattern — «шаблон соли», нечто такое, что невероятно усложняет взлом пароля. Советую изменить дефолтные значения на какие-нибудь свои

База данных
———————————————
Создадим в нашей базе данных таблицу пользователей

CREATE TABLE `users` (
  `id` int(11) unsigned NOT NULL auto_increment,
  `username` varchar(32) NOT NULL default '',
  `password` char(50) NOT NULL default '',
  `email` varchar(127) NOT NULL default '',
  `join` int(10) unsigned NOT NULL default '0',
  `last_login` int(10) unsigned NOT NULL default '0',
  `logins` int(10) unsigned NOT NULL default '0',
  PRIMARY KEY  (`id`),
  UNIQUE KEY `uniq_username` (`username`),
  UNIQUE KEY `uniq_email` (`email`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `users` (`id`, `username`, `password`, `email`, `join`, `last_login`, `logins`) VALUES
(1, 'admin', 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX', 'example@example.com', 0, 0, 0);

Поля таблицы думаю в принципе понятны. В поле password будут хранитьcя хитро-солёные хеши пароля.

Кроме пароля и индивидуальных настроек у каждого пользователя может быть своя роль. Типовые роли хранятся в специальной таблице ролей.

CREATE TABLE `roles` (
  `id` int(4) unsigned NOT NULL auto_increment,
  `name` varchar(32) NOT NULL,
  `description` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`),
  UNIQUE KEY `uniq_name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;

INSERT INTO `roles` (`id`, `name`, `description`) VALUES
(1, 'login', 'Разрешён вход в систему.'),
(2, 'admin', 'Пример специфичной роли - Администратор');

Роль login является обязательной и предопределена фреймворком. Она означает возможность заходить на сайт вообще, и должна быть у любого пользователя. Отсутствие его фактически означает бан.

У каждого пользователя может быть несколько ролей. Соответствие ролей и пользователей хранится в отдельной таблице

CREATE TABLE `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=MyISAM DEFAULT CHARSET=utf8;

INSERT INTO `roles_users` (`user_id`, `role_id`) VALUES
(1, 2),
(1, 1);

В этом примере таблицы у пользователя №1 (‘admin’) указано две роли №1(‘login’) и №2(‘admin’).

Для запоминания на сервере сессии пользователя ведётся таблица user_tokens

CREATE TABLE `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 `user_id` (`user_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

Все таблицы, которые здесь приведены — MyISAM. Если есть желание использовать InnoDB, то можно ещё и внешние ключи подкрутить. Хотя выигрыш от InnoDB наверное не так велик. Таблицы пользователей и доступов довольно консервативны. Впрочем всё должно идти от конкретной цели.

Использование в коде
—————————————-
Использование не очень сложное. В контроллере, который требует авторизации просто нужно использовать Auth::instance(). Чтобы не дёргать инстанс каждый раз, в конструкторе контроллера надо инициализировать некую переменную, например $auth:

class Controller_Admin extends Controller
{
    protected $auth;
    protected $user;
	public function before() {
		parent::before();
                
		$this->auth = Auth::instance();				
		$this->user = $this->auth->get_user();
								
                    ..........................
                      

В этом примере, мы также завели свойство контроллера $user, используя функцию get_user(). Эта функция извлекает данные о пользователе. Если пользователь не залогинился, то функция возвращает FALSE.

Другие функции auth
———————————

  • login($username, $password, $remember = FALSE) — Собственно функция авторизации. Если авторизация проходит успешно, то возвращает TRUE. Иначе FALSE.

    Параметр $remember аналогичен галочке «Запомнить меня»

  • auto_login() — Попытка автоматического входа. Имеет смысл, если перед этим выполнялся вход с включенной опцией «Запомнить меня»
  • force_login($username) — Принудительный логин без указания пароля. Например, для входа в систему используя секретную ссылку
  • logout($destroy = FALSE) — Выход. Параметр $destroy указывает, стоит ли полностью уничтожать сессию, или достаточно просто разлогиниться, а прочие данные сессии сохранить
  • logged_in($role = NULL) — Функция, которая позволяет проверить, выполнен ли вход. Кроме банального логина может проверять наличие нужной роли.
  • change_password(array & $array, $save = FALSE) — Функция изменения пароля текущего пользователя. Массив $array должен содержать поля ‘password’ и ‘password_confirm’. В случае их несовпадения возвращает FALSE.

    По-умолчанию не сохраняет изменённый пароль. Для сохранения нужно вызвать $user->save(), либо сразу вызывать с парамером $save=TRUE;

Вот такое сумбурное у меня знакомство получилось. :)

Модуль AUTH в Kohana: 19 комментариев

  1. Altesack

    @ BIakaVeron:
    По замыслу — один раз при создании инициализирую свойства и потом юзаю $this->auth и $this->user во всём контроллере

  2. Altesack

    @ BIakaVeron:
    Ах да. Этот класс у меня не базовый. Я у себя его не наследую. В таком контексте оно не важно. Пожалуй исправлю

  3. BIakaVeron

    ИМХО, private имеет смысл использовать только когда явно надо закрыть доступ потомкам, в остальных случаях — protected. Даже если Вы сейчас не планируете наследование, оно может пригодиться позже (может даже не Вам)

  4. Andrey

    Что то сложновато все с этой Kohana.
    Пожылуй из за таких сложностей все и бегут на тот же WP или какой другой движок для сайта.

  5. IceDragon

    @ Andrey:
    Это не готовая система для сайта, это фреймворк — т.е. кирпичи для построения движка для сайта. и Auth — просто один из кирпичиков.

  6. Евгений

    а помоему всё достаточно просто по сравнению с другими фреймворками. да и сравнивать цмс с фреймворком это как сравнивать масло и маргарин

  7. Сергей

    Евгений пишет:

    а помоему всё достаточно просто по сравнению с другими фреймворками. да и сравнивать цмс с фреймворком это как сравнивать масло и маргарин

    Скорее всего как масло с с молоком, из которого делается масло :)

  8. Дмитрий

    «Использование не очень сложное. В контроллере, который требует авторизации просто нужно использовать Auth::instance(). Чтобы не дёргать инстанс каждый раз, в конструкторе контроллера надо инициализировать некую переменную, например $auth»

    Если заглянуть в код метода Auth::instance:

    public static function instance()
    {
    if ( ! isset(Auth::$_instance))
    {
    // Load the configuration for this type
    $config = Kohana::config(‘auth’);
    if ( ! $type = $config->get(‘driver’))
    {
    $type = ‘ORM’;
    }

    // Set the session class name
    $class = ‘Auth_’.ucfirst($type);

    // Create a new session instance
    Auth::$_instance = new $class($config);
    }

    return Auth::$_instance;
    }

    то мы увидим, что в Kohana кешируются все инстансы. Незачем создавать дополнительные переменные ))

  9. lazycommit

    @ Дмитрий:
    здесь, наверное, автор имел ввиду не «дёргать» а писать каждый раз Auth::instance() или Auth::$_instance

  10. Николай

    «Потом заходим в modules/auth/config/auth.php и вносим свои настройки»

    Другие модули менять не стоит, я думаю будет лучше скопировать файл с конфигом в APPPATH.»config» и уже там править как хочется. Тогда при обновлении данного модуля, проблем не будет.

  11. mydwld

    подскажи, как получить данные об авторизованном пользователе после проверки logged_in? например мне нужны его id и логин. как я понял работать нужно через get_user, но как дальше обработать полученный результат?

  12. mydwld

    вот пример из статьи:

    $this->auth = Auth::instance();
    $this->user = $this->auth->get_user();

    как из $this->user вытащит id и login ?

  13. altesack Автор записи

    get_user() возвращает фактически ORM модель. Так что можно вытащить любое поле из таблицы users

    Например
    $this->user->username
    $this->user->id

    и т.д.

    Если иногда непонятна суть получаемых структур — просто выводите
    Kohana::debug($this->user)

  14. BASSON

    А есть статьи про то как осуществить регистрацию пользователя и вообще есть ли примеры простых блогов/сайтов с авторизацией на Auth еснно в исходниках?

  15. raul

    change_password()
    похоже исключили из последней сборки.
    вообще какая то не понятная хрень с этим модулем.
    пытаюсь сделать восстановление+смену пароля. хэширую пароль через hash_password($new_pass) сохраняю. и не входит

    $new_pass = Text::random(‘alnum’ , 8);
    $user->password = $this->auth->hash_password($new_pass ) ;
    $user->save();
    $this->auth->login($user->username ,$new_pass); // выводит 0
    $this->user = $this->auth->get_user();

Комментарии запрещены.