Alexander Makarov
10 years ago
2 changed files with 215 additions and 1 deletions
@ -0,0 +1,214 @@
|
||||
Аутентификация |
||||
============== |
||||
|
||||
Аутентификация это процесс проверки подлинности пользователя. Обычно используется идентификатор |
||||
(например `username` или адрес электронной почты) и секретный токен (например пароль или ключ доступа), чтобы судить о |
||||
том что пользователь именно тот за кого себя выдаёт. Аутентификация является основной функуцией формы входа. |
||||
|
||||
Yii обеспечивает фреймворк авторизации с различнымы компонентами обеспечивающими процесс входа. |
||||
Для использования этого фреймворка, вам нужно проделать следующее: |
||||
|
||||
* Настроить компонент приложения [[yii\web\User|user]]; |
||||
* Создать класс реализующии интерфейс [[yii\web\IdentityInterface]]. |
||||
|
||||
|
||||
## Настройка [[yii\web\User]] <span id="configuring-user"></span> |
||||
|
||||
Компонент [[yii\web\User|user]] управляет статусом аутентификации пользователя. |
||||
Он требует, чтоб вы указали [[yii\web\User::identityClass|identity class]], который будет содержать |
||||
текущую логику аутентификации. В следующей конфигурации приложения, [[yii\web\User::identityClass|identity class]] для |
||||
[[yii\web\User|user]] задан как `app\models\User`, реализация которого будет объяснена в следующем разделе: |
||||
|
||||
```php |
||||
return [ |
||||
'components' => [ |
||||
'user' => [ |
||||
'identityClass' => 'app\models\User', |
||||
], |
||||
], |
||||
]; |
||||
``` |
||||
|
||||
|
||||
## Реализация [[yii\web\IdentityInterface]] <span id="implementing-identity"></span> |
||||
|
||||
[[yii\web\User::identityClass|identity class]] должен реализовывать [[yii\web\IdentityInterface]], |
||||
который содержит следующие методы: |
||||
|
||||
* [[yii\web\IdentityInterface::findIdentity()|findIdentity()]]: Этот метод находит экземпляр `identity class`, |
||||
используя ID пользователя. Этот метод используется, когда необходимо поддерживать состояние аутентификации через сессии. |
||||
* [[yii\web\IdentityInterface::findIdentityByAccessToken()|findIdentityByAccessToken()]]: Этот метод находит экземпляр `identity class`, |
||||
используя токен доступа. Этот метод используется когда нужно аутентифицировать пользователя |
||||
по единственному секретному токену (например в RESTful приложениях, не сохраняющих состояние между запросами). |
||||
* [[yii\web\IdentityInterface::getId()|getId()]]: Этот метод возвращает ID пользователя представленного данным экземпляром `identity`. |
||||
* [[yii\web\IdentityInterface::getAuthKey()|getAuthKey()]]: Этот метод возвращает ключ используемый для основанной на `cookie` аутентификации. |
||||
Ключ сохраняется в аутентификационной cookie и позже сравниватеся с версией находящейся на сервере, |
||||
чтоб удостоверится что аутентификационная `cookie` верная. |
||||
* [[yii\web\IdentityInterface::validateAuthKey()|validateAuthKey()]]: Этот метод реализует логику проверки ключа |
||||
для основанной на `cookie` аутентификации. |
||||
|
||||
Если какой-то из методов не требуется, то можно реализовать его с пустым телом. Для примера, |
||||
если у вас RESTful приложение, не сохраняющее состояние между запросами, вы можете реализовать только |
||||
[[yii\web\IdentityInterface::findIdentityByAccessToken()|findIdentityByAccessToken()]] |
||||
и [[yii\web\IdentityInterface::getId()|getId()]] тогда как остальные методы оставить пустыми. |
||||
|
||||
В следующем примере, [[yii\web\User::identityClass|identity class]] реализован |
||||
как класс [Active Record](db-active-record.md) связанный с таблицей `user`. |
||||
|
||||
```php |
||||
<?php |
||||
|
||||
use yii\db\ActiveRecord; |
||||
use yii\web\IdentityInterface; |
||||
|
||||
class User extends ActiveRecord implements IdentityInterface |
||||
{ |
||||
public static function tableName() |
||||
{ |
||||
return 'user'; |
||||
} |
||||
|
||||
/** |
||||
* Finds an identity by the given ID. |
||||
* |
||||
* @param string|integer $id the ID to be looked for |
||||
* @return IdentityInterface|null the identity object that matches the given ID. |
||||
*/ |
||||
public static function findIdentity($id) |
||||
{ |
||||
return static::findOne($id); |
||||
} |
||||
|
||||
/** |
||||
* Finds an identity by the given token. |
||||
* |
||||
* @param string $token the token to be looked for |
||||
* @return IdentityInterface|null the identity object that matches the given token. |
||||
*/ |
||||
public static function findIdentityByAccessToken($token, $type = null) |
||||
{ |
||||
return static::findOne(['access_token' => $token]); |
||||
} |
||||
|
||||
/** |
||||
* @return int|string current user ID |
||||
*/ |
||||
public function getId() |
||||
{ |
||||
return $this->id; |
||||
} |
||||
|
||||
/** |
||||
* @return string current user auth key |
||||
*/ |
||||
public function getAuthKey() |
||||
{ |
||||
return $this->auth_key; |
||||
} |
||||
|
||||
/** |
||||
* @param string $authKey |
||||
* @return boolean if auth key is valid for current user |
||||
*/ |
||||
public function validateAuthKey($authKey) |
||||
{ |
||||
return $this->getAuthKey() === $authKey; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
Как обьяснялось ранее, вам нужно реализовать только `getAuthKey()` и `validateAuthKey()` если ваше приложение использует |
||||
только аутентификацию основанную на `cookie`. В этом случае, вы можете использовать следующий код для генерации |
||||
ключа аутентификации для каждого пользователя и хранения его в таблице `user`: |
||||
|
||||
```php |
||||
class User extends ActiveRecord implements IdentityInterface |
||||
{ |
||||
...... |
||||
|
||||
public function beforeSave($insert) |
||||
{ |
||||
if (parent::beforeSave($insert)) { |
||||
if ($this->isNewRecord) { |
||||
$this->auth_key = \Yii::$app->security->generateRandomString(); |
||||
} |
||||
return true; |
||||
} |
||||
return false; |
||||
} |
||||
} |
||||
``` |
||||
|
||||
> Замечание: Не путайте `identity` класс `User` с классом [[yii\web\User]]. Первый является классом реализующим |
||||
логику аутентификации пользователя. Он часто реализуется как класс [Active Record](db-active-record.md) связанный |
||||
с некоторым постоянным хранилищем где лежит информация о пользователях. Второй, это класс компонента приложения |
||||
отвечающий за управление состоянием аутентификации пользователя. |
||||
|
||||
|
||||
## Использование [[yii\web\User]] <span id="using-user"></span> |
||||
|
||||
В основном класс [[yii\web\User]] используют как компонент приложения `user`. |
||||
|
||||
Можно получить `identity` текущего пользователя используя выражение `Yii::$app->user->identity`. Оно вернёт экземпляр |
||||
[[yii\web\User::identityClass|identity class]] представляющий текущего аутентифицированного пользователя, |
||||
или `null` если текущий пользователь не аутентифицирован (например гость). Следующий код показывает как получить |
||||
другую связанную с аутентификацией информацию из [[yii\web\User]]: |
||||
|
||||
```php |
||||
// `identity` текущего пользователя. `Null` если пользователь не аутентифицирован. |
||||
$identity = Yii::$app->user->identity; |
||||
|
||||
// ID текущего пользователя. `Null` если пользователь не аутентифицирован. |
||||
$id = Yii::$app->user->id; |
||||
|
||||
// проверка на то, что текущий пользователь гость (не аутентифицирован) |
||||
$isGuest = Yii::$app->user->isGuest; |
||||
``` |
||||
|
||||
Для залогинивания пользователя, вы можете использовать следующий код: |
||||
|
||||
```php |
||||
// найти identity с указанным username. |
||||
// замечание: также вы можете проверить и пароль, если это нужно |
||||
$identity = User::findOne(['username' => $username]); |
||||
|
||||
// логиним пользователя |
||||
Yii::$app->user->login($identity); |
||||
``` |
||||
|
||||
Метод [[yii\web\User::login()]] устанавливает `identity` текущего пользователя в [[yii\web\User]]. Если сессии |
||||
[[yii\web\User::enableSession|включены]], то `identity` будет сохраняться в сессии, так что состояние |
||||
статуса аутентификации будет поддерживаться на всём протяжении сессии. Если основанный на cookie вход |
||||
(так называемый "запомни меня" вход) [[yii\web\User::enableAutoLogin|включен]], то `identity` также будет сохранена |
||||
в `cookie` так чтобы статус аутентификации пользователя мог быть восстановлен на протяжении всего времени жизни `cookie`. |
||||
|
||||
Для включения входа основанного на `cookie`, вам нужно установить [[yii\web\User::enableAutoLogin]] в `true` |
||||
в конфигурации приложения. Вы также можете настроить время жизни передав его при вызове метода [[yii\web\User::login()]]. |
||||
|
||||
Для выхода пользователя, просто вызовите |
||||
|
||||
```php |
||||
Yii::$app->user->logout(); |
||||
``` |
||||
|
||||
Обратите внимание: выход пользователя имеет смысл только если сессии включены. Метод сбрасывает статус аутентификации |
||||
сразу и из памяти и из сессии. И по умолчанию, будут также уничтожены *все* сессионные данные пользователя. |
||||
Если вы хотите сохранить сессионные данные, вы должны вызвать `Yii::$app->user->logout(false)`, вместо этого. |
||||
|
||||
|
||||
## События аутентификации <span id="auth-events"></span> |
||||
|
||||
Класс [[yii\web\User]] вызывает несколько событий во время процессов входа и выхода. |
||||
|
||||
* [[yii\web\User::EVENT_BEFORE_LOGIN|EVENT_BEFORE_LOGIN]]: вызвается перед вызовом [[yii\web\User::login()]]. |
||||
Если обработчик устанавливает свойство [[yii\web\UserEvent::isValid|isValid]] объекта в `false`, |
||||
процесс входа будет прерван. |
||||
* [[yii\web\User::EVENT_AFTER_LOGIN|EVENT_AFTER_LOGIN]]: вызывается после успешного входа. |
||||
* [[yii\web\User::EVENT_BEFORE_LOGOUT|EVENT_BEFORE_LOGOUT]]: вызывается перед вызовом [[yii\web\User::logout()]]. |
||||
Если обработчик устанавливает свойство [[yii\web\UserEvent::isValid|isValid]] объекта в `false`, |
||||
процесс выхода будет прерван. |
||||
* [[yii\web\User::EVENT_AFTER_LOGOUT|EVENT_AFTER_LOGOUT]]: вызывается после успешного выхода. |
||||
|
||||
Вы можете использовать эти события для реазлизации функции аудита входа, статистике онлайн пользователей. Для примера, |
||||
в обработчике для [[yii\web\User::EVENT_AFTER_LOGIN|EVENT_AFTER_LOGIN]], вы можете сделать запись о времени и IP |
||||
адресе входа в таблицу `user`. |
Loading…
Reference in new issue