mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-12 02:56:55 +01:00
484 lines
37 KiB
Plaintext
484 lines
37 KiB
Plaintext
Аутентифікація і авторизація
|
||
============================
|
||
|
||
Аутентифікація і авторизація необхідні на сторінках, доступних лише деяким користувачам. *Аутентифікація* - перевірка, чи є хтось тим, за кого себе видає. Зазвичай вона має на увазі введення логіна і пароля, але також можуть бути використані й інші засоби, такі як використання смарт-карти, відбитків пальців та ін. *Авторизація* - перевірка, чи може аутентифікований користувач виконувати певні дії (їх часто позначають як ресурси). Найчастіше це визначається перевіркою, чи призначена користувачеві певна роль, яка має доступ до ресурсів.
|
||
|
||
У Yii вбудований зручний фреймворк аутентифікації і авторизації (auth), який, у разі необхідності, може бути налаштовано під ваші завдання.
|
||
|
||
Центральним компонентом auth-фреймворку є визначений *компонент додатку «користувач»* — обʼєкт, який реалізує інтерфейс [IWebUser]. Даний компонент містить постійну інформацію про поточного користувача. Ми можемо отримати до неї доступ з будь-якого місця програми, використовуючи `Yii::app()->user`.
|
||
|
||
Використовуючи цей компонент, ми можемо перевірити, чи аутентифікований користувач, використовуючи [CWebUser::isGuest]. Ми можемо зробити [вхід|CWebUser::login] або [вихід|CWebUser::logout]. Для перевірки прав на певні дії зручно скористатися [CWebUser::checkAccess]. Також є можливість отримати [унікальний ідентифікатор|CWebUser::name] та інші постійні дані користувача.
|
||
|
||
Визначення класу Identity
|
||
-------------------------
|
||
|
||
Як було згадано раніше, аутентифікація - це процес перевірки особистості користувача. Типовий веб-додаток для такої перевірки зазвичай використовує логін і пароль. Тим не менш, може знадобитися реалізувати перевірку іншими методами. Щоб додати підтримку різних методів аутентифікації, в Yii є відповідний identity клас.
|
||
|
||
Ми реалізуємо клас identity, який містить потрібну нам логіку аутентифікації. Такий клас повинен реалізувати інтерфейс [IUserIdentity]. Для різних підходів до аутентифікації можуть бути реалізовані різні класи (наприклад, OpenID, LDAP, Twitter OAuth або Facebook Connect). При створенні своєї реалізації необхідно розширити клас [CUserIdentity], який є базовим класом, який реалізує перевірку за логіном і паролем.
|
||
|
||
Головне завдання при створенні класу Identity — реалізація методу [IUserIdentity::authenticate]. Даний метод використовується для опису основного алгоритму аутентифікації. Також, даний клас може містити додаткову інформацію про користувача, яка необхідна нам в процесі роботи з його сесією.
|
||
|
||
#### Приклад
|
||
|
||
У наведеному нижче прикладі ми використовуємо клас identity і покажемо, як реалізувати аутентифікацію по базі даних. Даний підхід типовий для більшості додатків. Користувач буде вводити логін і пароль у форму. Введені дані перевірятимемо з використанням моделі [ActiveRecord](/doc/guide/database.ar), відповідної таблиці користувача в БД. У даному прикладі показано наступне:
|
||
|
||
1. Реалізація методу `authenticate()` для перевірки даних по БД.
|
||
2. Перекриття методу `CUserIdentity::getId()` для повернення `_id`. За умовчанням як ID повертається імʼя користувача.
|
||
3. Використання методу `setState()` ([CBaseUserIdentity::setState]) для зберігання інформації, необхідної при кожному запиті.
|
||
|
||
~~~
|
||
[php]
|
||
class UserIdentity extends CUserIdentity
|
||
{
|
||
private $_id;
|
||
public function authenticate()
|
||
{
|
||
$record=User::model()->findByAttributes(array('username'=>$this->username));
|
||
if($record===null)
|
||
$this->errorCode=self::ERROR_USERNAME_INVALID;
|
||
else if($record->password!==md5($this->password))
|
||
$this->errorCode=self::ERROR_PASSWORD_INVALID;
|
||
else
|
||
{
|
||
$this->_id=$record->id;
|
||
$this->setState('title', $record->title);
|
||
$this->errorCode=self::ERROR_NONE;
|
||
}
|
||
return !$this->errorCode;
|
||
}
|
||
|
||
public function getId()
|
||
{
|
||
return $this->_id;
|
||
}
|
||
}
|
||
~~~
|
||
|
||
У наступному підрозділі ми розглянемо реалізацію входу і виходу, використовуючи наш identity клас у методі `login` користувача. Вся інформація, яку ми зберігаємо у станах (шляхом виклику [CBaseUserIdentity::setState]) буде передана у [CWebUser], який, у свою чергу, буде зберігати її в постійному сховищі, такому як сесії. До даної інформації можна буде звертатися як до властивостей [CWebUser]. У нашому прикладі ми зберегли імʼя користувача, використовуючи `$this->setState('title', $record->title);`. Як тільки користувач успішно увійде у додаток, ми зможемо отримати його `title` використовуючи `Yii::app()->user->title`.
|
||
|
||
> Info|Інформація: За замовчуванням [CWebUser] використовує сесії для зберігання даних. Якщо ви використовуєте автоматичний вхід користувача за допомогою cookie ([CWebUser::allowAutoLogin] встановлений у `true`), дані користувача будуть також зберігатися у cookie. Переконайтеся, що ці дані не містять конфіденційної інформації, такої як паролі.
|
||
|
||
Вхід и вихід
|
||
------------
|
||
|
||
Тепер, коли ми розібрали приклад реалізації класу identity, ми можемо використовувати його для реалізації входу і виходу:
|
||
|
||
~~~
|
||
[php]
|
||
// Аутентифікуємо користувача по імені і паролю
|
||
$identity=new UserIdentity($username,$password);
|
||
if($identity->authenticate())
|
||
Yii::app()->user->login($identity);
|
||
else
|
||
echo $identity->errorMessage;
|
||
…
|
||
// Виходимо
|
||
Yii::app()->user->logout();
|
||
~~~
|
||
|
||
Ми створюємо новий обʼєкт UserIdentity і передаємо в його конструктор параметри аутентифікації (тобто `$username` і `$password`, введені користувачем). Далі просто викликаємо метод `authenticate()`. У разі успішної перевірки даних ми передаємо обʼєкт в метод [CWebUser::login], який зберігає інформацію в постійному сховищі (за замовчуванням у сесіях PHP) і робить її доступною у наступних запитах. Якщо аутентифікація не проходить, ми можемо отримати інформацію про помилку із властивості `errorMessage`.
|
||
|
||
Перевірити, чи є користувач аутентифікованим, дуже просто. Для цього можна скористатися `Yii::app()->user->isGuest`. При використанні постійного сховища, такого як сесії (за замовчуванням) та/або cookie (описано нижче), для зберігання інформації про користувача, користувач може залишатися аутентифікованим у наступних запитах. У цьому випадку немає необхідності використовувати клас UserIdentity і показувати форму входу. [CWebUser] автоматично завантажить необхідну інформацію із постійного сховища і використовує її при зверненні до `Yii::app()->user->isGuest`.
|
||
|
||
Вхід на основі cookie
|
||
---------------------
|
||
|
||
За замовчуванням, після деякого часу бездіяльності, що залежить від [налаштувань сесії](http://php.net/manual/en/session.configuration.php), буде проведений вихід із системи. Для того, щоб цього не відбувалося, необхідно виставити властивості компонента User [allowAutoLogin|CWebUser::allowAutoLogin] в `true` і передати необхідний час життя cookie у метод [CWebUser::login]. Користувач буде автоматично аутентифікований на сайті протягом зазначеного часу навіть у тому випадку, якщо він закриє браузер. Дана можливість вимагає підтримки cookie в браузері користувача.
|
||
|
||
~~~
|
||
[php]
|
||
// Автоматичний вхід протягом 7 днів.
|
||
// allowAutoLogin для компонента user повинен бути виставлений в true.
|
||
Yii::app()->user->login($identity,3600*24*7);
|
||
~~~
|
||
|
||
Як вже згадувалося раніше, коли увімкнений вхід на основі cookie, стани,
|
||
які зберігаються за допомогою [CBaseUserIdentity::setState], також будуть зберігатися в cookie.
|
||
При наступному вході стани зчитуються із cookie та стають доступними через `Yii::app()->user`.
|
||
|
||
Недивлячись на те, що у Yii є засоби для запобігання заміни станів у cookie
|
||
на стороні клієнта, не рекомендується зберігати у станах важливу інформацію.
|
||
Набагато крашим рішенням буде зберігання її у постійному сховищі на стороні сервера (наприклад, у БД).
|
||
|
||
Крім того, для серйозних додатків рекомендується поліпшити стратегію входу по cookie наступним чином:
|
||
|
||
* При успішному вході після заповнення форми генерируємо та зберігаємо випадковий ключ
|
||
як в cookie стану, так і у постійному сховищі на сервері (тобто у БД)
|
||
|
||
* При наступних запитах, коли аутентифікація виконується на основі
|
||
інформації у cookie, ми порівнюємо дві копії ключа та, перед тим, як
|
||
аутентифікувати користувача, перевіряємо, що вони рівні.
|
||
|
||
* Якщо користувач входить через форму ще раз, ключ регенерується.
|
||
|
||
Дана стратегія виключає можливість повторного використання старого
|
||
стану cookie, у якому може знаходитися застаріла інформація.
|
||
|
||
Для реалізації необхідно перевизначити два методи:
|
||
|
||
* [CUserIdentity::authenticate()]. Тут виконується аутентифікація.
|
||
Якщо користувач аутентифікований, необхідно згенерувати новий ключ та зберегти його
|
||
у cookie стану (за допомогою [CBaseUserIdentity::setState]) і у постійному сховищі
|
||
на стороні сервера (наприклад, у БД).
|
||
|
||
* [CWebUser::beforeLogin()]. Викликається перед входом. Необхідно перевірити відповідність ключів у стані та базі даних.
|
||
|
||
Фільтр контролю доступа
|
||
-----------------------
|
||
|
||
Фільтр контролю доступа — схема авторизації, яка має на увазі попередню перевірку
|
||
прав поточного користувача на дію контролера, що викликається. Авторизація
|
||
виконується по імені користувача, IP-адреси та типу запита. Цей фільтр називається
|
||
«[accessControl|CController::filterAccessControl]».
|
||
|
||
> Tip|Підказка: Фільтр контролю доступа достатній для реалізації простих систем.
|
||
Для більш складних ви можете використовувати доступ на основі ролей
|
||
(RBAC), який буде описано нижче.
|
||
|
||
Для управління доступом до дій контролера необхідно перевизначити метод
|
||
[CController::filters] (більш докладно описано у розділі [Фільтри](/doc/guide/basics.controller#filter)).
|
||
|
||
~~~
|
||
[php]
|
||
class PostController extends CController
|
||
{
|
||
…
|
||
public function filters()
|
||
{
|
||
return array(
|
||
'accessControl',
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Вище було описано, що фільтр [access
|
||
control|CController::filterAccessControl] застосовується до всіх дій контролера `PostController`.
|
||
Правила доступу, використовувані фільтром, визначаються
|
||
перевизначенням методу [CController::accessRules] контролера.
|
||
|
||
~~~
|
||
[php]
|
||
class PostController extends CController
|
||
{
|
||
…
|
||
public function accessRules()
|
||
{
|
||
return array(
|
||
array('deny',
|
||
'actions'=>array('create', 'edit'),
|
||
'users'=>array('?'),
|
||
),
|
||
array('allow',
|
||
'actions'=>array('delete'),
|
||
'roles'=>array('admin'),
|
||
),
|
||
array('deny',
|
||
'actions'=>array('delete'),
|
||
'users'=>array('*'),
|
||
),
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Наведений код описує три правила, кожне з яких представлено у вигляді масиву. Перший елемент масиву може приймати значення `'allow'` або `'deny'`.
|
||
Решта пар ключ-значення задають параметри правила. Правила, задані вище, можна прочитати таким чином: дії `create` і `edit` не можуть бути виконані анонімними користувачами, а дія `delete` може бути виконана тільки користувачами із роллю `admin`.
|
||
|
||
Правила доступу розбираються по черзі у порядку їх опису. Перше правило, яке збігається із поточними даними (наприклад, з імʼям користувача, роллю або IP) визначає результат авторизації. Якщо це дозволяє правило, дія може бути виконана, якщо забороняє - не може. Якщо жодне з правил не співпало - дія може бути виконана.
|
||
|
||
> Tip|Підказка: Щоб бути впевненим, що дія не буде виконана,
|
||
> необхідно заборонити всі дії, які не дозволені, визначивши відповідне
|
||
> правило у кінці списку:
|
||
> ~~~
|
||
> [php]
|
||
> return array(
|
||
> // … різні правила …
|
||
> // це правило повністю забороняє дію 'delete'
|
||
> array('deny',
|
||
> 'actions'=>array('delete'),
|
||
> ),
|
||
> );
|
||
> ~~~
|
||
> Дане правило необхідне, тому що якщо жодне з правил не співпаде,
|
||
> дія продовжить виконання.
|
||
|
||
Правило доступу може включати параметри, за якими перевіряється збігання:
|
||
|
||
- [actions|CAccessRule::actions]: дозволяє вказати дії у вигляді масиву їх ідентифікаторів. Порівняння регістронезалежне;
|
||
|
||
- [controllers|CAccessRule::controllers]: дозволяє вказати контролери у вигляді масиву їх ідентифікаторів. Порівняння регістронезалежне;
|
||
|
||
- [users|CAccessRule::users]: дозволяє вказати користувачів. Для порівняння використовується [CWebUser::name]. Порівняння регістронезалежне.У параметрі можуть бути використані наступні спеціальні символи:
|
||
|
||
- `*`: будь-який користувач, включаючи анонімного;
|
||
- `?`: анонімний користувач;
|
||
- `@`: аутентифікований користувач.
|
||
|
||
- [roles|CAccessRule::roles]: дозволяє вказати ролі, використовуючи
|
||
[доступ на основі ролей](/doc/guide/topics.auth#sec5), описаний у наступному розділі.
|
||
У окремому випадку, право застосується, якщо [CWebUser::checkAccess]
|
||
поверне `true` для однієї з ролей. Ролі варто використовувати в дозвільних правилах, так як роль асоціюється із можливістю виконання якої-небудь дії.
|
||
Також варто відзначити, що, незважаючи на те, що ми використовуємо термін «роль», значенням може бути будь-який елемент auth-фреймворку, такий як ролі, завдання або операції;
|
||
|
||
- [ips|CAccessRule::ips]: дозволяє вказати IP-адрес;
|
||
|
||
- [verbs|CAccessRule::verbs]: дозволяє вказати тип запитів (наприклад, `GET` або `POST`).
|
||
Порівняння регістронезалежне;
|
||
|
||
- [expression|CAccessRule::expression]: дозволяє вказати вираз PHP, обчислення якого буде визначати збіг правила. Усередині виразу доступна змінна `$user`, яка вказує на `Yii::app()->user`.
|
||
|
||
|
||
Обробка запиту авторизації
|
||
--------------------------
|
||
|
||
При невдалій авторизації, тобто коли користувачу заборонено виконувати вказану дію, відбувається наступне:
|
||
|
||
- Якщо користувач не аутентифікований і у властивості [loginUrl|CWebUser::loginUrl]
|
||
компонента `user` заданий URL сторінки входу, браузер буде перенаправлений на цю сторінку.
|
||
Зауважимо, що за замовчуванням [loginUrl|CWebUser::loginUrl] перенаправляє до сторінки `site/login`;
|
||
|
||
- Інакше буде відображена помилка HTTP із кодом 403.
|
||
|
||
При завданні властивості [loginUrl|CWebUser::loginUrl] використовується як відносний,
|
||
так і абсолютний URL. Також можна передати масив, який буде використовуватися
|
||
[CWebApplication::createUrl] при формуванні URL. Перший елемент масиву задає [маршрут](/doc/guide/basics.controller#route) до дії login вашого
|
||
контролера, а інші пари імʼя-значення - GET-параметри. Приміром:
|
||
|
||
~~~
|
||
[php]
|
||
array(
|
||
…
|
||
'components'=>array(
|
||
'user'=>array(
|
||
// це значення встановлюється за замовчуванням
|
||
'loginUrl'=>array('site/login'),
|
||
),
|
||
),
|
||
)
|
||
~~~
|
||
|
||
Якщо браузер був перенаправлений на сторінку входу і вхід вдалий, вам може знадобитися перенаправити користувача до тієї сторінці, на якій невдало пройшла авторизація. Як же дізнатися URL тієї сторінки? Ми можемо отримати цю інформацію з властивості [returnUrl|CWebUser::returnUrl] компонента `user`.
|
||
Маючи її, ми можемо зробити перенаправлення:
|
||
|
||
~~~
|
||
[php]
|
||
Yii::app()->request->redirect(Yii::app()->user->returnUrl);
|
||
~~~
|
||
|
||
Контроль доступу на основі ролей
|
||
--------------------------------
|
||
|
||
Контроль доступу на основі ролей (RBAC) — простий, але потужний спосіб централізованого контролю доступу. Для порівняння даного методу з іншими зверніться до
|
||
[статті у Вікіпедії](http://ru.wikipedia.org/wiki/%D3%EF%F0%E0%E2%EB%E5%ED%E8%E5_%E4%EE%F1%F2%F3%EF%EE%EC_%ED%E0_%EE%F1%ED%EE%E2%E5_%F0%EE%EB%E5%E9).
|
||
|
||
В Yii ієрархічний RBAC реалізований через компонент [authManager|CWebApplication::authManager].
|
||
Нижче, ми спочатку опишемо основи даної схеми, потім те, як описувати дані, необхідні для авторизації.
|
||
На завершення ми покажемо, як використовувати ці дані для контролю доступу.
|
||
|
||
### Загальні принципи
|
||
|
||
Основним поняттям у RBAC Yii є *елемент авторизації*.
|
||
Елемент авторизації — це права на виконання якої-небудь дії (створити новий запис у блозі, управління користувачами).
|
||
В залежності від структури і цілі, елементи авторизації можуть бути розділені на *операції*, *завдання* і *ролі*.
|
||
Роль складається із завдань. Завдання складається з операцій. Операція - дозвіл на будь-яку дію (далі не ділиться). Наприклад, у системі може бути роль `адміністратор`, що складається із завдань `керування записами` і `керування користувачами`. Задача `керування користувачами` може складатися з операцій `створити користувача`, `редагувати користувача` і `видалити користувача`. Для досягнення більшої гнучкості, роль в Yii може складатися з інших ролей і операцій. Завдання може складатися з інших завдань. Операція - з інших операцій.
|
||
|
||
Елемент авторизації однозначно ідентифікується його унікальним імʼям.
|
||
|
||
Елемент авторизації може бути асоційований із *бізнес-правилом* — PHP-кодом, який буде використовуватися при перевірці доступу. Користувач отримає доступ до елемента тільки якщо код поверне `true`.
|
||
Наприклад, при визначенні операції `updatePost`, буде не зайвим додати бізнес-правило, що перевіряє відповідність ID користувача ID автора запису. Тобто, доступ до редагування запису має тільки її автор.
|
||
|
||
Використовуючи елементи авторизації, ми можемо побудувати *ієрархію авторизації*.
|
||
Елемент `A` є батьком елемента `B` в ієрархії, якщо `A` складається із `B` (або `A` успадковує права, представлені в `B`). Елемент може мати кілька нащадків і кілька предків. Тому ієрархія авторизації є скоріше частково упорядкованим графом, ніж деревом. У ній ролі перебувають на верхніх рівнях, операції - на нижніх. Посередині розташовані завдання.
|
||
|
||
Після побудови ієрархії авторизації, ми можемо призначати ролі із неї користувачам нашого додатку.
|
||
Користувач отримує всі права ролі, яка йому призначена. Приміром, якщо призначити користувачу роль `адміністратор`, він отримає адміністративні повноваження, такі як `керування записами` або `керування користувачами` (і відповідні їм операції, такі як `створити користувача`).
|
||
|
||
А тепер найприємніше. У дії контролера хочемо перевірити, чи може поточний користувач видалити певний запис.
|
||
При використанні ієрархії RBAC і призначеної користувачеві ролі, це робиться дуже просто:
|
||
|
||
~~~
|
||
[php]
|
||
if(Yii::app()->user->checkAccess('deletePost'))
|
||
{
|
||
// видаляємо запис
|
||
}
|
||
~~~
|
||
|
||
Налаштування менеджера авторизації
|
||
----------------------------------
|
||
|
||
Перед тим, як ми перейдемо до побудови ієрархії авторизації і безпосередньо перевірці доступу, нам буде потрібно налаштувати компонент додатку
|
||
[authManager|CWebApplication::authManager]. В Yii є два типи менеджерів авторизації:
|
||
[CPhpAuthManager] та [CDbAuthManager]. Перший використовує для зберігання даних PHP, другий - базу даних.
|
||
При налаштуванні [authManager|CWebApplication::authManager] необхідно вказати, який з компонентів ми збираємося використовувати і вказати початкові значення властивостей компонента. Приміром:
|
||
|
||
~~~
|
||
[php]
|
||
return array(
|
||
'components'=>array(
|
||
'db'=>array(
|
||
'class'=>'CDbConnection',
|
||
'connectionString'=>'sqlite:path/to/file.db',
|
||
),
|
||
'authManager'=>array(
|
||
'class'=>'CDbAuthManager',
|
||
'connectionID'=>'db',
|
||
),
|
||
),
|
||
);
|
||
~~~
|
||
|
||
Після цього, ми можемо звертатися до компонента [authManager|CWebApplication::authManager]
|
||
використовуючи `Yii::app()->authManager`.
|
||
|
||
Побудова ієрархії авторизації
|
||
-----------------------------
|
||
|
||
Побудова ієрархії авторизації складається з трьох етапів:
|
||
завдання елементів авторизації, описи звʼязків між ними і призначення ролей користувачам.
|
||
компонент [authManager|CWebApplication::authManager]
|
||
надає повний набір API для виконання поставлених завдань.
|
||
|
||
Для визначення елемента авторизації слід скористатися одним із наведених нижче методів:
|
||
|
||
- [CAuthManager::createRole]
|
||
- [CAuthManager::createTask]
|
||
- [CAuthManager::createOperation]
|
||
|
||
Після того, як ми визначили набір елементів авторизації, ми можемо скористатися наступними методами для встановлення звʼязків:
|
||
|
||
- [CAuthManager::addItemChild]
|
||
- [CAuthManager::removeItemChild]
|
||
- [CAuthItem::addChild]
|
||
- [CAuthItem::removeChild]
|
||
|
||
Після цього ми призначаємо ролі користувачам:
|
||
|
||
- [CAuthManager::assign]
|
||
- [CAuthManager::revoke]
|
||
|
||
Наведемо приклад побудови ієрархії авторизації з використанням даного API:
|
||
|
||
~~~
|
||
[php]
|
||
$auth=Yii::app()->authManager;
|
||
|
||
$auth->createOperation('createPost','створення запису');
|
||
$auth->createOperation('readPost','перегляд запису');
|
||
$auth->createOperation('updatePost','редагування запису');
|
||
$auth->createOperation('deletePost','видалення запису');
|
||
|
||
$bizRule='return Yii::app()->user->id==$params["post"]->authID;';
|
||
$task=$auth->createTask('updateOwnPost','редагування свого запису',$bizRule);
|
||
$task->addChild('updatePost');
|
||
|
||
$role=$auth->createRole('reader');
|
||
$role->addChild('readPost');
|
||
|
||
$role=$auth->createRole('author');
|
||
$role->addChild('reader');
|
||
$role->addChild('createPost');
|
||
$role->addChild('updateOwnPost');
|
||
|
||
$role=$auth->createRole('editor');
|
||
$role->addChild('reader');
|
||
$role->addChild('updatePost');
|
||
|
||
$role=$auth->createRole('admin');
|
||
$role->addChild('editor');
|
||
$role->addChild('author');
|
||
$role->addChild('deletePost');
|
||
|
||
$auth->assign('reader','readerA');
|
||
$auth->assign('author','authorB');
|
||
$auth->assign('editor','editorC');
|
||
$auth->assign('admin','adminD');
|
||
~~~
|
||
|
||
Після створення елементів авторизації, компонент [authManager|CWebApplication::authManager]
|
||
(або його спадкоємці, наприклад, [CPhpAuthManager], [CDbAuthManager]) завантажує їх автоматично.
|
||
Тобто, наведений код запускається один раз, а НЕ для кожного запиту.
|
||
|
||
> Info|Інфо: Досить громіздкий приклад вище призначений скоріше для демонстрації.
|
||
Розробникам звичайно потрібно створити інтерфейс адміністратора і дати можливість користувачам самим побудувати ієрархію авторизації.
|
||
|
||
Використання бізнес-правил
|
||
--------------------------
|
||
|
||
При побудові ієрархії авторизації ми можемо призначити роль, завдання або операцію *бізнес-правилу*.
|
||
Також ми можемо вказати його при призначенні ролі користувачу.
|
||
Бізнес-правило - PHP-код, що використовується при перевірці доступу. Значення, яке повертає даний код, визначає, чи застосовувати дану роль до активного користувача.
|
||
У прикладі вище ми застосували бізнес-правило для опису завдання `updateOwnPost`.
|
||
У ньому ми перевіряємо, чи збігається ID поточного користувача із ID автора запису.
|
||
Інформація про запис в масиві `$params` передається розробником при перевірці доступу.
|
||
|
||
### Перевірка доступу
|
||
|
||
Для перевірки доступу нам необхідно знати імʼя елемента авторизації.
|
||
Наприклад, щоб перевірити, чи може поточний користувач створити запис,
|
||
необхідно дізнатися, чи має він права, описані операцією `createPost`.
|
||
Після цього ми можемо викликати [CWebUser::checkAccess]:
|
||
|
||
~~~
|
||
[php]
|
||
if(Yii::app()->user->checkAccess('createPost'))
|
||
{
|
||
// створюємо запис
|
||
}
|
||
~~~
|
||
|
||
Якщо правило авторизації використовує бізнес-правило, що вимагає додаткових параметрів, необхідно їх передати. Наприклад, щоб перевірити, чи може користувач редагувати запис, ми передаємо дані про запис в `$params`:
|
||
|
||
~~~
|
||
[php]
|
||
$params=array('post'=>$post);
|
||
if(Yii::app()->user->checkAccess('updateOwnPost',$params))
|
||
{
|
||
// оновлюємо запис
|
||
}
|
||
~~~
|
||
|
||
|
||
### Використання ролей за замовчуванням
|
||
|
||
Деяким веб-додаткам потрібні дуже специфічні ролі, які призначаються кожному або майже кожному користувачу.
|
||
Приміром, нам необхідно наділити деякими правами всіх аутентифікованих користувачів.
|
||
Визначати явно і зберігати ролі для кожного користувача в цьому випадку явно незручно.
|
||
Для вирішення цієї проблеми можна використовувати *ролі за замовчуванням*.
|
||
|
||
Роль за умовчанням автоматично призначається кожному користувачеві, включаючи гостей.
|
||
При виклику [CWebUser::checkAccess] спочатку перевіряються ролі за замовчуванням.
|
||
Призначати їх явно не потрібно.
|
||
|
||
Ролі за замовчуванням описуються у властивості [CAuthManager::defaultRoles].
|
||
Наприклад, наведена нижче конфігурація описує дві ролі за замовчунням:
|
||
`authenticated` та `guest`.
|
||
|
||
~~~
|
||
[php]
|
||
return array(
|
||
'components'=>array(
|
||
'authManager'=>array(
|
||
'class'=>'CDbAuthManager',
|
||
'defaultRoles'=>array('authenticated', 'guest'),
|
||
),
|
||
),
|
||
);
|
||
~~~
|
||
|
||
Так як роль за умовчанням призначається кожному користувачу, звичайно потрібно використовувати бізнес-правило, що визначає, до яких саме користувачів її застосовувати. Наприклад, наступний код визначає дві ролі:
|
||
`authenticated` і `guest`, які відповідно застосовуються до аутентифікованих користувачів та гостей.
|
||
|
||
~~~
|
||
[php]
|
||
$bizRule='return !Yii::app()->user->isGuest;';
|
||
$auth->createRole('authenticated', 'аутентифікований користувач', $bizRule);
|
||
|
||
$bizRule='return Yii::app()->user->isGuest;';
|
||
$auth->createRole('guest', 'гість', $bizRule);
|
||
~~~
|
||
|
||
> Info|Інформація: Починаючи із версії 1.1.11 масив `$params`, який передається до бізнес правила, має ключ `userId`, значення цього ключа це id користувача, для якого ми перевіряємо бізнес правило. Вам було б це потрібно, якщо б ви викликали [CDbAuthManager::checkAccess()] або [CPhpAuthManager::checkAccess()] у місцях, де `Yii::app()->user` відсутній або перевіряєте доступ для іншого користувача.
|
||
|
||
<div class="revision">$Id: topics.auth.txt 2890 2011-01-18 15:58:34Z qiang.xue $</div> |