Авторизация
Авторизация пользователей является нередкой задачей при построении приложения. Kohana реализует ее через встроенный модуль Auth
. Этот модуль работает по системе «драйверов», вы можете выбрать, каким методом производить авторизацию (по умолчанию Kohana предоставляет файловую авторизацию и драйвер ORM
). Помимо этого, возможно написать свой собственный драйвер.
Конфигурация
Файл конфигурации по умолчанию находится в config/auth.php
в соответствии со структурой файловой системы. Для настройки доступны следующий параметры:
-
driver
— Название драйвера аутентификации, по умолчанию этоfile
. -
hash_method
— Хеш-функция для паролей, по умолчанию этоsha256
. -
hash_key
— Ключ, используемый при хэшировании пароля, по умолчанию он не указан и рекомендуется установить его в произвольное целое число. -
session_type
— Тип сессии для хранения авторизации пользователя, по умолчанию это стандартная сессия для приложения (Session::$default
). -
session_key
— Имя переменной сессии для хранения авторизации пользователя, по умолчаниюauth_user
.
Базовые действия
Вы можете создать произвольный объект авторизации через стандартный конструктор классов, в этом случае, конструктору нужно передать полностью всю конфигурацию:
$auth = new Auth_ORM(array( 'hash_method' => 'sha256', 'hash_key' => 5856739, 'session_key' => 'custom_auth', )); $auth2 = new Auth_File(array( 'hash_method' => 'sha256', 'hash_key' => 5856739, 'session_key' => 'custom_auth_2', ));
Таким образом, можно реализовывать несколько одновременных авторизаций. Однако, чаще подразумевается только одна одновременная авторизация, и ее реализуют с помощью конструкции singleton
:
$auth = Auth::instance(); // конфигурация в этом случае берется из файла config/auth.php
Эта конструкция доступна из любого места в приложении (будь то контроллер, модель или представление), и рекомендуется использовать именно ее.
Любой драйвер авторизации предоставляет следующие методы:
-
Вход
-
Выход
-
Проверка, совершен ли вход
-
Метод для доступа к данным пользователя
Рассмотрим их подробнее.
Вход
Вход совершается с помощью метода login($username, $password)
, где $username
— имя пользователя и $password
— его пароль. Пример совершения авторизации:
$username = 'test'; $password = 'foobar'; if (Auth::instance()->login($username, $password)) { // Авторизация прошла успешно } else { // Ошибка при авторизации }
Выход
Выход реализуется с помощью метода logout($destroy)
, где $destroy
— необязательный флаг, при котором уничтожается полностью вся сессия:
Auth::instance()->logout(TRUE);
Проверка на вход
Чтобы проверить, авторизован ли пользователь, можно использовать метод logged_in()
:
if(Auth::instance()->logged_in()) { echo 'Hello, user!'; }
Получение информации
Для получения информации о текущем пользователе доступен метод get_user($default)
, где $default
— необязательный параметр, который будет возвращен, если авторизация не выполнена. Пример:
if(Auth::instance()->logged_in()) { $user = Auth::instance()->get_user(); echo 'Hello, '.$user['username']; }
Драйвера
Рассмотрим более подробную работу с каждым из драйверов.
File
Для файлового драйвера доступны следующие конфигурационные настройки:
-
users
— массив, индексами которого являются имена пользователей, а элементами — их пароли (в хешированном виде).
Авторизация в файловом драйвере происходит именно по массиву users
в конфигурационном файле. Поэтому, для файлового драйвера проблематично создать автоматическую регистрацию, смену пароля и изменение профиля. В основном этот драйвер используется для админ-панели, где эти функции не требуются.
Файловый драйвер встроенной авторизации Kohana предоставляет совсем немного расширенных методов, разберем их подробнее:
Принудительный вход
Иногда требуется совершить принудительный вход в систему, без указания пароля. Для этого существует метод force_login($username)
, где $username
— имя пользователя, для которого нужно совершить вход. Пример:
Auth::instance()->force_login('admin');
ORM
На фоне простого файлового драйвера более интересным выглядит драйвер авторизации через ORM. В списке его функциональных возможностей:
-
Возможность регистрации и изменения профиля
-
Система ролей (прав) пользователей
-
Встроенная возможность «бана» пользователей
-
Запоминание авторизации на длительное время
Помимо базовых, для драйвера доступны следующие настройки:
-
lifetime
— время, на которое будет запоминаться сессия авторизации (в секундах), по умолчанию это1209600
(две недели).
При использовании этого драйвера, модуль Auth будет представлять данные пользователя в виде ORM-модели класса Model_User
. Соответственно, необходимо подключить сам модуль ORM в файле bootstrap
. Код sql для создания таблиц находится в файлах MODPATH/orm/auth-schema-mysql.sql
(для MySQL) и MODPATH/orm/auth-schema-postgresql.sql
( для PostgreSQL), необходимо импортировать его в базу данных перед началом использования модуля.
По умолчанию для модели аккаунта предопределены следующие поля:
-
email
— электронная почта -
username
— имя пользователя -
password
— хеш пароля -
logins
— количество входов в систему -
last_login
— unix timestamp последнего входа
Вы можете расширить эти поля по собственному усмотрению. Если для этого нужно расширить саму модель, вы можете переопределить ее, наследуя от класса Model_Auth_User
:
class Model_User extends Model_Auth_User { protected $_table_name = 'custom_user'; }
По умолчанию, модель user
содержит связи с моделями user_token
и role
. Вы можете переопределить и их, наследуя по такому же принципу.
Роли
С помощью этого драйвера возможно каждому пользователю присваивать определенные роли (права), позволяющие разграничивать их по статусу. Например, для пользователя-администратора доступны роли login
, edit
, delete
и read
, а обычному пользователю только login
и read
. Это означает, что обычный пользователь имеет права только входить и читать, а администратор еще и редактировать и удалять.
Реализация происходит через связь ORM «много ко многому» (has many through
) в модели user
к модели role
. Прежде, чем начать работать с ролями, вы должны предопределить их список в базе данных в таблице roles
(обычно это делают вручную).
Чтобы проверить, имеет ли пользователь определенную роль, нужно использовать метод logged_in($role)
, где $role
— название или массив названий (name
) ролей, либо загруженный объект роли:
if( ! Auth::instance()->logged_in('edit')) { throw new HTTP_Exception_403('Вы не имеете право редактировать запись'); }
Вход
Мы рассматриваем функцию входа снова, потому что она потерпела несколько важных изменений:
-
Вход в систему может производиться как по логину, так и по email одновременно
-
Для метода
login
доступен третий аргумент$remember
, при установлении которого вTRUE
авторизационная сессия сохраняется на указанное в настройкеlifetime
время. -
Авторизация будет успешной только тогда, когда пользователь имеет роль
login
.
Пример авторизации с запоминанием сессии:
$email = $_POST['email']; $password = $_POST['password']; $remember = isset($_POST['remember']) && $_POST['remember']; if( ! Auth::instance()->login($email, $password, $remember)) { echo 'Невозможно выполнить вход'; }
Запоминание сессии идет с помощью токенов (user_token
) — случайно сгенеированных строк, которые одновременно записываются и в cookie и в базу данных. Когда обычная сессия заканчивается, то проверяется наличие той самой cookie с токеном, если он найден, то происходит поиск его в базе, и, если он найден, то происходит автоматический логин.
Выход
Метод выхода содержит еще один аргумент, помимо базового — $logout_all
. При установке этого аргумента в TRUE
, помимо текущего токена уничтожаются еще и все остальные для этого пользователя.
Пример использования:
Auth::instance()->logout(FALSE, TRUE); // выходим, уничтожаем все токены, но оставляем сессию
Регистрация
Kohana предлагает совершать регистрацию пользователей минуя конструкции ORM с помощью метода create_user($valus, $expected)
, где $values
— массив данных вставляемого пользователя, индексами которого являются названия полей, а элементами — их значения, и опциональный аргумент $expected
— массив названий полей, которых нужно извлечь из первого массива. Если второй параметр оставить пустым, то данные будут использованы все.
Пример регистрации:
ORM::factory('user') ->create_user($_POST, array('username', 'email', 'password'));
В этом случае пользователь будет создан из полей $_POST['username']
, $_POST['email']
и $_POST['password']
.
Обратите внимание, что после такой регистрации пользователь в базе появится, однако вы не сможете войти через него, т.к. отсутствует роль login
. В случае, если вы хотите «активировать» пользователя сразу поле регистрации, полный код будет выглядеть так:
try { $user = ORM::factory('user') ->create_user($_POST, array('username', 'email', 'password')) // Регистрируем пользователя ->add('roles', ORM::factory('role', array('name' => 'login'))); // Добавляем роль login // Регистрация успешна } catch(ORM_Validation_Exception $e) { $errors = $e->errors(); // Допущены ошибки при вводе данных }
Разработка драйверов
Вы можете легко создать свой драйвер, для этого нужно создать наследованный от Auth
класс в папке classes/auth
. Как минимум, класс должен содержать реализации следующих абстрактных методов:
abstract protected function _login($username, $password, $remember); abstract public function password($username); abstract public function check_password($password);
Обычно, требуют доработки и эти методы, поэтому обратите свое внимание и на них:
public function logged_in($role); public function get_user($default);
После создания, класс драйвера будет иметь имя вида Auth_Example
, где example
— имя драйвера, которое нужно указывать в конфигурации.