Разработка сайта для Вашего бизнеса. Веб дизайн. Дизайн логотипа, фирменного стиля, рекламная фотография . Комплексный рекламный креатив.

Ralex. We do the work.
На рынке с 1999го года. Средняя ценовая категория. Ориентация на эффективность решений.
Ознакомтесь с нашим портфолио
Узнайте больше о услугах
Свяжитесь с нами:
E-mail: [email protected]
Tel: (044) 587 - 84 - 78
Custom web design & дизайн и разработка сайта "под ключ"
Креативный, эффективный дизайн. Система управления сайтом (СУС).
Custom flexible разработка систем электронной коммерции
Система e-commerce разрабатывается под индивидуальные потребности. Гибкая функциональность.
Search Engine Optimzation & оптимизация под поисковые системы (SEO)
Постоянная оптимизация и мониторинг сайта в поисковых системах. Достигаем результата быстро и эффективно
Custom logo design & дизайн логотипа и фирменного стиля
Многолетний опыт. Огромное портфолио. Уникальное предложение и цена.
профессиональная рекламная фотография
креативно, смело, качественно
Custom logo design & рекламный креатив. дизайн рекламы
Многолетний опыт. Огромное портфолио. Уникальное предложение и цена.

Personal Maps: авторизація та аутентифікація (з використанням Yii RBAC). Частина 9.

  1. Структура правил RBAC
  2. авторизація користувачів
  3. Створення правил RBAC
  4. аутентифікація користувачів
  5. Контролер і модель для роботи з користувачами
  6. висновок

Наша взаимовыгодная связь https://banwar.org/

У попередніх статтях цього циклу ми практично завершили створення нашого web додатки (посилання на попередні статті ви знайдете внизу цієї сторінки). Ми можемо створювати і редагувати об'єкти, відображати їх на карті. Але для повноцінної роботи програми нам необхідно створювати користувачів з різними рівнями доступу, а також перевіряти їх права при зверненні до програми.

Перш ніж переходити до системи розмежування доступу, давайте розберемося, які типи користувачів потрібні для нашого застосування.

Передбачається, що кожен користувач буде тільки зі своїми об'єктами, то нам буде достатньо двох рівнів доступу:

  • user - звичайний користувач, може працювати тільки зі своїми об'єктами;
  • admin - адміністратор, може працювати зі своїми об'єктами, а також створювати, змінювати і видаляти інших користувачів.

Тобто адміністратор має ті ж самі права, що і звичайний користувач, плюс кілька додаткових. Реалізувати таку систему розмежування доступу найзручніше за допомогою RBAC (Role Based - Управління доступом на основі ролей).

Примітка. Вихідний код програми розміщений на GitHub, також доступна демоверсія програми.

Source Demo

Структура правил RBAC

В Yii фреймворк входить зручна бібліотека для реалізації такого управління доступом, яка підтримує три елементи авторизації: операції (operations), завдання (tasks) і ролі (roles). Роль може включати в себе кілька завдань, а кожна задача - кілька операцій.

Розглянемо, як ці елементи авторизації пов'язані між собою в нашому додатку.

В першу чергу ми визначаємо операції користувачів (ліва колонка на малюнку). Оскільки додаток у нас досить просте, операцій небагато. Фактично ми визначили тільки CRUD операції для об'єктів типу Place і User.

авторизація користувачів

Процедура авторизації передбачає перевірку прав користувача на доступ до запитаного ресурсу або виконання якоїсь операції.

Ця перевірка виконується в методах контролера (до того як ми що-небудь відправили користувачеві) за допомогою методу checkAccess:

public function actionIndex () {if (Yii :: app () -> user-> checkAccess ( 'viewPlaces')) {$ this-> render ( 'index'); } Else {$ this-> redirect (array ( 'site / login')); }}

Якщо поточний користувач має відповідні права, метод checkAccess поверне true і буде показана головна сторінка додатка, якщо немає - відбудеться редирект на сторінку з формою введення логіна і пароля.

Трохи складніше використання задач. У нашому додатку у користувача не повинно бути можливості видалити чужі об'єкти. Тобто операція видалення повинна бути йому доступна, але при цьому потрібно перевірити чи належить об'єкт йому. Для цього використовуються завдання (tasks). При їх створенні ми визначаємо так зване «бізнес правило». У ньому ми повинні порівняти id поточного користувача зі значенням поля p_user_id обраного об'єкта.

Тобто бізнес правило буде виглядати так:

return Yii :: app () -> user-> id == $ params [ "place"] -> p_user_id;

При цьому $ params містить дані, які передаються в другому параметрі checkAccess. У нашому випадку це буде об'єкт, який потрібно видалити. Тепер розглянемо метод видалення об'єкта.

public function actionDelete ($ id) {$ place = Places :: model () -> findByPk ($ id); if (null === $ place) {$ this -> _ sendResponse (404, CJSON :: encode (array ( 'message' => 'Could not find place with id ='. $ id))); return; } If (! Yii :: app () -> user-> checkAccess ( 'deletePlace', array ( 'place' => $ place))) {$ this -> _ sendResponse (403); return; } If ($ place-> delete ()) {$ this -> _ sendResponse (200, CJSON :: encode ($ place)); } Else {$ this -> _ sendResponse (500, CJSON :: encode (array ( 'message' => 'Could not delete place', 'errors' => $ place-> getErrors (),))); }}

Запит на видалення виглядає наступним чином

/ Api / places / id

В першу чергу ми шукаємо об'єкт, який має вказаний id. Якщо об'єкт не знайдено, відправляємо 404-ую помилку.

Потім виконуємо перевірку прав користувача. Зверніть увагу, в методі checkAccess ми перевіряємо права на виконання операції deletePlace, але при цьому передаємо в другому параметрі масив з знайденим об'єктом. Оскільки для операції deletePlace визначено завдання viewOwnPlace при перевірці доступу буде використано бізнес правило цього завдання. І якщо значення p_user_id не збігається з id користувача, метод поверне false.

Створення правил RBAC

  1. Правила, які використовуються для перевірок, повинні десь зберігатися. Це може бути як файл, так і база даних. Ми використовуємо другий варіант.
  2. Правила потрібно створити. Для цього можна реалізувати web інтерфейс, який дозволить редагувати правила для різних груп користувачів. Але тому що у нас не передбачається можливість зміни зв'язків між ролями, операціями і завданнями, ми створимо їх за допомогою консольної команди.

Спочатку створимо таблиці, в яких будуть зберігатися правила. Їх схема зберігається в файлі framework / web / auth / schema-mysql.sql. Просто імпортуємо його в базу і в результаті у нас з'являться три нові таблиці: authassignment, authitem і authitemchild.

Тепер нам потрібно вказати Yii, що ми хочемо зберігати правила в базі. Для цього в config / main.php налаштуємо компонент authManager.

'Components' => array (... 'authManager' => array ( 'class' => 'CDbAuthManager', 'connectionID' => 'db',), ...),

Напишемо консольную команду.

Для цього створюємо файл protected / commands / AccessCommand.php з двома методами.

class AccessCommand extends CConsoleCommand {public function actionAddRules () {...} public function actionAddAdminUser () {...}}

Перший метод створює правила, другий - додає користувача з правами адміністратора. Для того щоб їх викликати потрібно з консолі (з папки protected) виконати команди

yiic access addRules yiic access addAdminUser

Розглянемо створення правил

public function actionAddRules () {$ auth = Yii :: app () -> authManager; $ Auth-> createOperation ( 'addPlace', 'create place'); $ Auth-> createOperation ( 'viewPlace', 'view place'); $ Auth-> createOperation ( 'updatePlace', 'update place'); $ Auth-> createOperation ( 'deletePlace', 'delete place'); $ Auth-> createOperation ( 'viewPlaces', 'view places'); $ Auth-> createOperation ( 'addUser', 'create user'); $ Auth-> createOperation ( 'viewUser', 'view user'); $ Auth-> createOperation ( 'updateUser', 'update user'); $ Auth-> createOperation ( 'deleteUser', 'delete user'); $ Auth-> createOperation ( 'viewUsers', 'view users'); $ BizRule = 'return Yii :: app () -> user-> id == $ params [ "place"] -> p_user_id;'; $ Task = $ auth-> createTask ( 'viewOwnPlace', 'view own place', $ bizRule); $ Task-> addChild ( 'viewPlace'); $ Task = $ auth-> createTask ( 'updateOwnPlace', 'edit own place', $ bizRule); $ Task-> addChild ( 'updatePlace'); $ Task = $ auth-> createTask ( 'deleteOwnPlace', 'delete own place', $ bizRule); $ Task-> addChild ( 'deletePlace'); $ Role = $ auth-> createRole ( 'user'); $ Role-> addChild ( 'addPlace'); $ Role-> addChild ( 'viewOwnPlace'); $ Role-> addChild ( 'updateOwnPlace'); $ Role-> addChild ( 'deleteOwnPlace'); $ Role-> addChild ( 'viewPlaces'); $ Role = $ auth-> createRole ( 'admin'); $ Role-> addChild ( 'user'); $ Role-> addChild ( 'addUser'); $ Role-> addChild ( 'viewUser'); $ Role-> addChild ( 'updateUser'); $ Role-> addChild ( 'deleteUser'); $ Role-> addChild ( 'viewUsers'); }

Спочатку ми отримуємо authManager за допомогою якого виконується створення операцій, завдань і ролей. Кожна операція створюється за допомогою методу createOperation, в першому параметрі якого ми вказуємо ім'я операції, в другому - опис.

Потім за допомогою createTask створюємо завдання, для кожної з них вказуємо бізнес правило. І за допомогою методу addChild «прив'язуємо» операцію до задачі. Тепер при перевірці прав доступу до операції буде використана відповідна задача. Тобто в першому параметрі checkAccess ми в будь-якому випадку вказуємо назву операції, а не завдання.

Для створення ролі використовується метод createRole. Після цього до ролі за допомогою методу addChild «прив'язуємо» операції, завдання та інші ролі.

Зверніть увагу. До брати участь admin ми не «прив'язуємо» операції на кшталт viewPlace, тому що у нас адміністратор повинен отримати всі права користувача ми «прив'язуємо» роль user. На малюнку кожна стрілка відповідає викликом методу addChild, тобто «Прив'язці» одного об'єкта до іншого. В результаті виходить ієрархічне спадкування прав.

аутентифікація користувачів

Процедура аутентифікації передбачає перевірку справжності користувача. У нашому випадку вона полягає в перевірці логіна і пароля.

Перш за все, створимо клас UserIdentity з методом authenticate (protected / components / UserIdentity.php)

class UserIdentity extends CUserIdentity {private $ _id; public function authenticate () {$ record = Users :: model () -> findByAttributes (array ( 'u_name' => $ this-> username)); if ($ record === null) {$ this-> errorCode = self :: ERROR_USERNAME_INVALID; } Else if ($ record-> u_pass! == crypt ($ this-> password, $ record-> u_pass)) {$ this-> errorCode = self :: ERROR_PASSWORD_INVALID; } Else {$ this -> _ id = $ record-> id; $ This-> errorCode = self :: ERROR_NONE; } Return! $ This-> errorCode; } Public function getId () {return $ this -> _ id; } / ** * Generate a random salt in the crypt (3) standard Blowfish format. * * @Param int $ cost Cost parameter from 4 to 31. * * @throws Exception on invalid cost parameter. * @Return string A Blowfish hash salt for use in PHP's crypt () * / public static function blowfishSalt ($ cost = 13) {if (! Is_numeric ($ cost) || $ cost <4 || $ cost> 31) { throw new Exception ( "cost parameter must be between 4 and 31"); } $ Rand = array (); for ($ i = 0; $ i <8; $ i + = 1) {$ rand [] = pack ( 'S', mt_rand (0, 0xffff)); } $ Rand [] = substr (microtime (), 2, 6); $ Rand = sha1 (implode ( '', $ rand), true); $ Salt = '$ 2a $'. sprintf ( '% 02d', $ cost). '$'; $ Salt. = Strtr (substr (base64_encode ($ rand), 0, 22), array ( '+' => '.')); return $ salt; }}

У методі authenticate (рядок 10) ми перевіряємо пароль за допомогою функції crypt . На сьогоднішній день, використання md5 для змішування паролів вважається не надійним, тому необхідно генерувати хеші на основі більш складних алгоритмів.

Функція crypt підтримує кілька алгоритмів хешування, в тому числі blowfish, який ми використовуємо в даному додатку. У першому параметрі crypt передається пароль, а в другому - сіль. При цьому, формат солі визначає алгоритм хешування. Функція поверне хеш пароля, який ми порівнюємо з хешем, який зберігається в базі даних.

Також в даний клас ми додали метод blowfishSalt, який формує хеш пароля в за алгоритмом blowfish.

Важливо! В Yii 1.1.14 з'явився клас CPasswordHelper , Який можна використовувати для виконання цієї ж завдання. Алгоритми будуть використовуватися ті ж самі, але ваш код буде коротшим. Зокрема, не доведеться реалізовувати метод blowfishSalt. Подробиці ви можете почитати в статті Use crypt () for password storage . До речі, код blowfishSalt я взяв зі старої версії цієї статті.

Тепер додамо команду, яка буде створювати аккаунт адміністратора.

class AccessCommand extends CConsoleCommand {... public function actionAddAdminUser () {$ auth = Yii :: app () -> authManager; $ User = new Users (); $ User-> u_name = 'admin'; $ User-> u_pass = 'admin'; $ User-> u_email = '[email protected]'; $ User-> u_role = 'admin'; $ User-> save (); }}

Для того, щоб ця команда правильно працювала, нам потрібно створити модель Users.

Контролер і модель для роботи з користувачами

Модель створюємо за допомогою gii і додаємо в неї два методи.

class Users extends CActiveRecord {... public function beforeSave () {$ this-> u_pass = crypt ($ this-> u_pass, UserIdentity :: blowfishSalt ()); return parent :: beforeSave (); } Public function afterSave () {$ assignments = Yii :: app () -> authManager-> getAuthAssignments ($ this-> id); if (! empty ($ assignments)) {foreach ($ assignments as $ key => $ assignment) {Yii :: app () -> authManager-> revoke ($ key, $ this-> id); }} Yii :: app () -> authManager-> assign ($ this-> u_role, $ this-> id); return parent :: afterSave (); }}

У методі beforeSave ми за допомогою blowfishSalt хешіруем пароль користувача перед збереженням його в БД.

Метод afterSave використовується для зв'язків між користувачем і правами доступу. Це необхідно для того, щоб адміністратор міг змінити права для вже створених користувачів.

В першу чергу за допомогою getAuthAssignments ми отримуємо масив всіх зв'язків між вказаними користувачем і елементами авторизації RBAC. Далі видаляємо всі існуючі зв'язки і потім, за допомогою методу assign, створюємо новий зв'язок. Нова зв'язок встановлюється на основі значення поля u_role. Тобто до конкретного користувача ми прив'язуємо ролі, а не операції або завдання.

Зверніть увагу. Користувач з роллю адміністратор фактично має дві ролі: admin і user, тому що роль admin успадковує user. Тому ми зберігаємо «головну» роль користувача в таблиці pm_users. І саме до цієї ролі «прив'язуємо» користувача за допомогою assign.

Контролер та подання для моделі Users ми також створюємо за допомогою gii.

Потім додаємо перевірку прав користувача в методи контролера. наприклад,

public function actionView ($ id) {if (Yii :: app () -> user-> checkAccess ( 'viewUser')) {$ this-> render ( 'view', array ( 'model' => $ this-> loadModel ($ id),)); } Else {throw new CHttpException (403); }}

І так далі для всіх методів, назви яких починаються з action. Таким чином, використовувати цей контролер зможе тільки адміністратор.

Відповідно в файлі views / layouts / yiistrap.php налаштуємо меню таким чином, щоб пункт «Користувачі» відображався тільки для адміністратора.

&lt;? Php $ this-> widget ( 'zii.widgets.CMenu', array ( 'items' => array (array ( 'label' => Yii :: t ( 'app', 'PLACES'), 'url' => array ( '/ places / index'), 'visible' =>! Yii :: app () -> user-> isGuest), array ( 'label' => Yii :: t ( 'app', 'USERS '),' url '=> array (' / users / index '),' visible '=> Yii :: app () -> user-> checkAccess (' viewUsers ')), array (' label '=> Yii :: t ( 'app', 'ABOUT'), 'url' => array ( '/ site / page', 'view' => 'about')), array ( 'label' => Yii :: t ( 'app', 'CONTACT'), 'url' => array ( '/ site / contact')), array ( 'label' => Yii :: t ( 'app', 'LOGIN'), 'url' = > array ( '/ site / login'), 'visible' => Yii :: app () -> user-> isGuest), array ( 'label' => Yii :: t ( 'app', 'LOGOUT') . '(' .Yii :: app () -> user-> name. ')', 'url' => array ( '/ site / logout'), 'visible' =>! Yii :: app () - > user-> isGuest)), 'activeCssClass' => 'active', 'htmlOptions' => array ( 'class' => 'nav',),)); ?>

У рядку 4 ми за допомогою checkAccess перевіряємо, чи може даний користувач переглядати список користувачів (/ users / index).

І як завершальний штрих трохи виправимо форму створення (редагування) користувача (файл views / users / _form.php)

&lt;? Php echo $ form-> errorSummary ($ model); ?> &lt;? Php echo $ form-> textFieldControlGroup ($ model, 'u_name', array ( 'span' => 5, 'maxlength' => 255)); ?> &lt;? Php echo $ form-> textFieldControlGroup ($ model, 'u_email', array ( 'span' => 5, 'maxlength' => 255)); ?> &lt;? Php echo $ form-> passwordFieldControlGroup ($ model, 'u_pass', array ( 'span' => 5, 'maxlength' => 255, 'value' => '')); ?> &lt;? Php echo $ form-> passwordFieldControlGroup ($ model, 'u_pass_repeat', array ( 'span' => 5, 'maxlength' => 255, 'value' => '')); ?> &lt;? Php echo $ form-> dropDownListControlGroup ($ model, 'u_role', array ( 'user' => 'user', 'admin' => 'admin'), array ( 'class' => 'span5' )); ?> <Div class = "form-actions"> &lt;? Php echo TbHtml :: submitButton ($ model-> isNewRecord? Yii :: t ( 'app', 'SAVE'): Yii :: t ( 'app', 'UPDATE'), array ( 'color' => TbHtml :: BUTTON_COLOR_PRIMARY, 'size' => TbHtml :: BUTTON_SIZE_LARGE,)); ?> </ Div> &lt;? Php $ this-> endWidget (); ?>

Зокрема, ми використовували метод dropDownListControlGroup для того, щоб створити список, що випадає з ролями користувачів. Gii створює звичайне текстове поле.

висновок

Використання RBAC особливої ​​складності не представляє. Найголовніше, спочатку продумати систему ролей таким чином, щоб її було легко і зручно розширювати. І пам'ятати, що перевіряти в контролерах потрібно операції, а ролі «прив'язувати» до користувачів. Тоді ви зможете створювати нові ролі з будь-яким набором прав, і при цьому не потрібно буде змінювати перевірки в контролерах і інші ролі.

Також раджу почитати статтю RBAC Авторизація в YII і LDAP . У ній більш докладно описується використання RBAC в Yii без прив'язки до певної програми.

Якщо є питання або зауваження, пишіть.
Успіхів!

зміст

Lt;?
Yii :: app () - > user-> isGuest)), 'activeCssClass' => 'active', 'htmlOptions' => array ( 'class' => 'nav',),)); ?
Php echo $ form-> errorSummary ($ model); ?
Php echo $ form-> textFieldControlGroup ($ model, 'u_name', array ( 'span' => 5, 'maxlength' => 255)); ?
Php echo $ form-> textFieldControlGroup ($ model, 'u_email', array ( 'span' => 5, 'maxlength' => 255)); ?
Php echo $ form-> passwordFieldControlGroup ($ model, 'u_pass', array ( 'span' => 5, 'maxlength' => 255, 'value' => '')); ?
Php echo $ form-> passwordFieldControlGroup ($ model, 'u_pass_repeat', array ( 'span' => 5, 'maxlength' => 255, 'value' => '')); ?
Php $ this-> endWidget (); ?
Категории
  • Биология
  • Математика
  • Краеведению
  • Лечебная
  • Наука
  • Физике
  • Природоведение
  • Информатика
  • Новости

  • Новости
    https://banwar.org/
    Наша взаимовыгодная связь https://banwar.org/. Запустив новый сайт, "Пари Матч" обещает своим клиентам незабываемый опыт и возможность выиграть крупные суммы.


    Наши клиенты
    Клиенты

    Быстрая связь

    Тел.: (044) 587-84-78
    E-mail: [email protected]

    Имя:
    E-mail:
    Телефон:
    Вопрос\Комментарий: