Управление привилегиями пользователя на основе ролей
Существуют различные подходы к управлению доступом к информации, каждый из них имеет свои плюсы и минусы. Например, использование битовой маски очень эффективно, но ограничено 32 или 64 уровнями (количеством бит в формате целого числа). А подход на основе списка доступа (ACL) позволяет назначать уровни доступа объектам, но с операциями могут возникнуть сложности.
В данной статье описывается реализация доступа на основе ролей (role based access control - RBAC). RBAC - модель системы разграничения прав доступа, в которой роли используются для выполнения различных задач, а разрешения на выполнение операций привязываются к ролям. Пользователь может получать одну или несколько ролей, которые ограничивают его полномочия на действия в системе.
Обратной стороной использования модели RBAC является то, что при плохом управлении ролями и разрешениями вся система доступа превращается в хаотичную массу. В быстро меняющейся бизнес среде может возникнуть необходимость в специальном операторе, который будет заниматься только отслеживанием назначений соответствующих ролей новым сотрудникам и удалений полномочий у тех, кто покинул компанию или сменил позицию в структуре. Определение новых ролей для возникающих рабочих мест, ревизия и удаление полномочий требуют постоянного контроля. Ошибка в управлении полномочиями может сделать брешь в системе безопасности.
Мы обсудим создание необходимых таблиц баз данных. Затем создадим два файла с классами: Role.php - для выполнения определенных задач по управлению ролями, и PrivilegedUser.php - для расширения класса пользователя. Затем приведем несколько примеров, как код может быть интегрирован в ваше приложение. Управление ролями и пользователями весьма похожи, поэтому у вас появится система для идентификации пользователей.
База данных
Нужно 4 таблицы для хранения ролей и информации о разрешениях: таблица roles содержит ID и имя роли, таблица permissions хранит ID и описание разрешения, таблица role_perm содержит соответствие ролей и разрешений, а таблица user_role содержит соответсвие ролей и пользователей.
С помощью такой схемы можно иметь неограниченное количество ролей и разрешений, а каждому пользователю может быть назначено любое число ролей.
Вот запрос CREATE TABLE для создания структуры в базе данных:
CREATE TABLE roles ( role_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, role_name VARCHAR(50) NOT NULL, PRIMARY KEY (role_id) ); CREATE TABLE permissions ( perm_id INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, perm_desc VARCHAR(50) NOT NULL, PRIMARY KEY (perm_id) ); CREATE TABLE role_perm ( role_id INTEGER UNSIGNED NOT NULL, perm_id INTEGER UNSIGNED NOT NULL, FOREIGN KEY (role_id) REFERENCES roles(role_id), FOREIGN KEY (perm_id) REFERENCES permissions(perm_id) ); CREATE TABLE user_role ( user_id INTEGER UNSIGNED NOT NULL, role_id INTEGER UNSIGNED NOT NULL, FOREIGN KEY (user_id) REFERENCES users(user_id), FOREIGN KEY (role_id) REFERENCES roles(role_id) );
Обратите внимание, что последняя таблица user_role ссылается на таблицу users, которая определяется в другом месте. В нашем случае мы предполагаем, что user_id является основным ключом в таблице users.
Никаких изменений для таблицы users не требуется, так как информация о правах доступа хранится отдельно. В отличие от других систем RBAC, в нашем случае пользователь не имеет никакой роли по умолчанию. Он просто не получает никаких полномочий. В классе PrivilegedUser возможно сделать обнаружение пользователей без ролей и выдачу роли без полномочий в таком случае. Или также можно сделать запрос SQL для копирования ID пользователей и инициализации их нужной ролью по умолчанию.
Класс Role
Основная цель класса Role - вернуть объект роли, который содержит список соответствующих полномочий. Таким образом можно просто проверить наличие нужных полномочий без дополнительных запросов SQL.
Вот код класса, который содержится в файле Role.php:
<?php
class Role
{
protected $permissions;
protected function __construct() {
$this->permissions = array();
}
// Возвращаем объект роли с соответствующими полномочиями
public static function getRolePerms($role_id) {
$role = new Role();
$sql = "SELECT t2.perm_desc FROM role_perm as t1
JOIN permissions as t2 ON t1.perm_id = t2.perm_id
WHERE t1.role_id = :role_id";
$sth = $GLOBALS["DB"]->prepare($sql);
$sth->execute(array(":role_id" => $role_id));
while($row = $sth->fetch(PDO::FETCH_ASSOC)) {
$role->permissions[$row["perm_desc"]] = true;
}
return $role;
}
// Проверка установленных полномочий
public function hasPerm($permission) {
return isset($this->permissions[$permission]);
}
}
Метод getRolePerms() создает новый объект Role на основе заданного ID роли. Затем использует выражение JOIN для комбинации таблиц role_perm и perm_desc. Каждое разрешение, связанное с ролью, хранится в виде описания в качестве ключа и значения true. Метод hasPerm() принимает описание разрешения и возвращает значение из текущего объекта.
Класс PrivilegedUser
С помощью нового класса, который дополняет существующий класс пользователя, можно использовать существующий код управления пользователями, дополняя его новыми методами для работы с привилегиями.
Код класса в файле PrivilegedUser.php:
<?php
class PrivilegedUser extends User
{
private $roles;
public function __construct() {
parent::__construct();
}
// Изменяем метод класса User
public static function getByUsername($username) {
$sql = "SELECT * FROM users WHERE username = :username";
$sth = $GLOBALS["DB"]->prepare($sql);
$sth->execute(array(":username" => $username));
$result = $sth->fetchAll();
if (!empty($result)) {
$privUser = new PrivilegedUser();
$privUser->user_id = $result[0]["user_id"];
$privUser->username = $username;
$privUser->password = $result[0]["password"];
$privUser->email_addr = $result[0]["email_addr"];
$privUser->initRoles();
return $privUser;
} else {
return false;
}
}
// Наполняем объект roles соответствующими разрешениями
protected function initRoles() {
$this->roles = array();
$sql = "SELECT t1.role_id, t2.role_name FROM user_role as t1
JOIN roles as t2 ON t1.role_id = t2.role_id
WHERE t1.user_id = :user_id";
$sth = $GLOBALS["DB"]->prepare($sql);
$sth->execute(array(":user_id" => $this->user_id));
while($row = $sth->fetch(PDO::FETCH_ASSOC)) {
$this->roles[$row["role_name"]] = Role::getRolePerms($row["role_id"]);
}
}
// Проверяем, обладет ли пользователь нужными разрешениями
public function hasPrivilege($perm) {
foreach ($this->roles as $role) {
if ($role->hasPerm($perm)) {
return true;
}
}
return false;
}
}
Метод getByUsername() возвращает объект, заполненный информацией о соответствующем пользователе. Метод почти идентичен тому, что обычно используется в класса пользователей, но его нужно изменить, чтобы добавить объект для ролей.
Метод initRoles() использует выражение JOIN для комбинирования таблиц user_role и roles для сбора информации о ролях для текущего пользователя. Каждая роль наполняется соответствующими разрешениями с помощью метода класса Role Role::getRolePerms().
Метод hasPrivilege() получает описание разрешения и возвращает результат проверки его наличия у текущего пользователя.
С помощью описанных двух классов проверка привилегий пользователя будет выполняться очень просто:
<?php
require_once "Role.php";
require_once "PrivilegedUser.php";
// Соединяемся с базой данных...
// ...
session_start();
if (isset($_SESSION["loggedin"])) {
$u = PrivilegedUser::getByUsername($_SESSION["loggedin"]);
}
if ($u->hasPrivilege("thisPermission")) {
// выполняем действие
}
Здесь имя пользователя хранится в активной сессии, и для него создается новый объект PrivilegedUser, для которого вызывается метод hasPrivilege(). В зависимости от информации, хранящейся в базе данных, объект может выглядеть следующим образом:
object(PrivilegedUser)#3 (2) {
["roles":"PrivilegedUser":private]=>
array(1) {
["Admin"]=>
object(Role)#5 (1) {
["permissions":protected]=>
array(4) {
["addUser"]=>bool(true)
["editUser"]=>bool(true)
["deleteUser"]=>bool(true)
["editRoles"]=>bool(true)
}
}
}
["fields":"User":private]=>
array(4) {
["user_id"]=>string(1) "2"
["username"]=>string(7) "mpsinas"
["password"]=>bool(false)
["email_addr"]=>string(0) ""
}
}
Организационные вопросы
Одним из преимуществ использования ООП для RBAC является возможность простого разделения логики и сервисных функций. Например, можно добавить следующие методы к классу Role для управления ролями (добавление, удаление, и так далее):
// Вставить новую роль
public static function insertRole($role_name) {
$sql = "INSERT INTO roles (role_name) VALUES (:role_name)";
$sth = $GLOBALS["DB"]->prepare($sql);
return $sth->execute(array(":role_name" => $role_name));
}
// Вставить массив ролей для заданного ID пользователя
public static function insertUserRoles($user_id, $roles) {
$sql = "INSERT INTO user_role (user_id, role_id) VALUES (:user_id, :role_id)";
$sth = $GLOBALS["DB"]->prepare($sql);
$sth->bindParam(":user_id", $user_id, PDO::PARAM_STR);
$sth->bindParam(":role_id", $role_id, PDO::PARAM_INT);
foreach ($roles as $role_id) {
$sth->execute();
}
return true;
}
// удалить массив ролей и все связи
public static function deleteRoles($roles) {
$sql = "DELETE t1, t2, t3 FROM roles as t1
JOIN user_role as t2 on t1.role_id = t2.role_id
JOIN role_perm as t3 on t1.role_id = t3.role_id
WHERE t1.role_id = :role_id";
$sth = $GLOBALS["DB"]->prepare($sql);
$sth->bindParam(":role_id", $role_id, PDO::PARAM_INT);
foreach ($roles as $role_id) {
$sth->execute();
}
return true;
}
// Удалить все роли для заданного пользователя
public static function deleteUserRoles($user_id) {
$sql = "DELETE FROM user_role WHERE user_id = :user_id";
$sth = $GLOBALS["DB"]->prepare($sql);
return $sth->execute(array(":user_id" => $user_id));
}
Также можно добавить подобные методы для класса PrivilegedUser:
// Проверка, обладает ли пользователь заданной ролью
public function hasRole($role_name) {
return isset($this->roles[$role_name]);
}
// Вставляем новое разрешение в роль
public static function insertPerm($role_id, $perm_id) {
$sql = "INSERT INTO role_perm (role_id, perm_id) VALUES (:role_id, :perm_id)";
$sth = $GLOBALS["DB"]->prepare($sql);
return $sth->execute(array(":role_id" => $role_id, ":perm_id" => $perm_id));
}
// Удаляем все разрешения из роли
public static function deletePerms() {
$sql = "TRUNCATE role_perm";
$sth = $GLOBALS["DB"]->prepare($sql);
return $sth->execute();
}Разрешения очень тесно связаны с логикой приложения, поэтому они требуют достаточно сложных процедур добавления и удаления. А роли можно легко модифицировать, создавать и удалять. с помощью интерфейса администратора.
Заключение
В данном уроке мы рассмотрели базу для системы управления доступом на основе использования ролей. Достаточно простой код позволяет построить гибкую масштабируемую систему разграничения прав пользователей. Однако должно внимание надо уделять управлению пользовательским полномочиями на этапе использования, иначе гибкость может привести к хаосу и неразберихе.
Источник: http://feedproxy.google.com/~r/ruseller/CdHX/~3/qtZVQdn1vhs/lessons.php
|
Существуют различные подходы к управлению доступом к информации, каждый из них имеет свои плюсы и минусы. Например, использование битовой маски очень эффективно, но ограничено 32 или 64 уровнями |
РэдЛайн, создание сайта, заказать сайт, разработка сайтов, реклама в Интернете, продвижение, маркетинговые исследования, дизайн студия, веб дизайн, раскрутка сайта, создать сайт компании, сделать сайт, создание сайтов, изготовление сайта, обслуживание сайтов, изготовление сайтов, заказать интернет сайт, создать сайт, изготовить сайт, разработка сайта, web студия, создание веб сайта, поддержка сайта, сайт на заказ, сопровождение сайта, дизайн сайта, сайт под ключ, заказ сайта, реклама сайта, хостинг, регистрация доменов, хабаровск, краснодар, москва, комсомольск |
Дайджест новых статей по интернет-маркетингу на ваш email
Новые статьи и публикации
- 2025-12-02 » Когда ошибка молчит: как бессмысленные сообщения ломают пользовательский опыт
- 2025-12-02 » 9 лучших бесплатных фотостоков
- 2025-12-02 » UTM-метки: ключевой инструмент аналитики для маркетолога
- 2025-12-02 » ПромоСтраницы Яндекса: Что такое и для чего служит
- 2025-12-02 » Метатеги для сайта: исчерпывающее руководство по Title, Description, Canonical, Robots и другим тегам
- 2025-11-26 » Оценка эффективности контента: превращаем информационный балласт в рабочий актив
- 2025-11-26 » 10 причин высокого показателя отказов на сайте
- 2025-11-26 » Когда и зачем обновлять структуру сайта
- 2025-11-26 » Скрытые демотиваторы: как мелочи разрушают эффективность команды
- 2025-11-26 » Зачем запускать MVP и как сделать это грамотно?
- 2025-11-20 » Половина российских компаний сократит расходы на транспорт и маркетинг в 2026 году
- 2025-11-20 » Перенос сайта с большим количеством ссылок
- 2025-11-20 » Перелинковка сайта: Что такое и как ее использовать
- 2025-11-20 » Критерии выбора SEO-специалиста и подрядчика для продвижения сайта
- 2025-11-20 » Применение искусственного интеллекта в рекламных агентствах: комплексное исследование трендов 2025 года
- 2025-11-19 » Геозапросы по-новому: как покорить локальное SEO с помощью ИИ
- 2025-11-14 » Консалтинг: сущность и ключевые направления
- 2025-11-14 » Онлайн-формы: универсальный инструмент для сбора обратной связи
- 2025-11-14 » Факторы конверсии органического трафика
- 2025-11-14 » Планирование рекламного бюджета: самостоятельный подход
- 2025-11-14 » Авторизация на сайте: как выбрать решение для удержания клиентов и сохранения продаж
- 2025-11-13 » Эффективные методы стимулирования клиентов к оставлению положительных отзывов
- 2025-11-13 » Налоговая реформа — 2026: грядущие изменения для предпринимателей
- 2025-11-13 » Альтернативы мессенджерам: что выбрать вместо Telegram и WhatsApp
- 2025-11-13 » Маркировка рекламы для начинающих: полное руководство по требованиям ЕРИР
- 2025-11-13 » ИИ не отберет вашу работу — её займет специалист, владеющий искусственным интеллектом
- 2025-10-29 » Как оценить эффективность работы SEO-специалиста: практическое руководство для маркетологов и владельцев бизнеса
- 2025-10-29 » Киберспорт как маркетинговый инструмент: стратегии привлечения геймеров
- 2025-10-29 » Как говорить с аудиторией о сложном
- 2025-10-29 » Что такое доказательства с нулевым разглашением (ZKP) и их роль в блокчейне
"Тот, кто в совершенстве овладеет электронной почтой, будет миллионером в двадцать первом веке." |
Мы создаем сайты, которые работают! Профессионально обслуживаем и продвигаем их , а также по всей России и ближнему зарубежью с 2006 года!
Как мы работаем
Заявка
Позвоните или оставьте заявку на сайте.
Консультация
Обсуждаем что именно Вам нужно и помогаем определить как это лучше сделать!
Договор
Заключаем договор на оказание услуг, в котором прописаны условия и обязанности обеих сторон.
Выполнение работ
Непосредственно оказание требующихся услуг и работ по вашему заданию.
Поддержка
Сдача выполненых работ, последующие корректировки и поддержка при необходимости.


Мы создаем практически любые сайты от продающих страниц до сложных, высоконагруженных и нестандартных веб приложений! Наши сайты это надежные маркетинговые инструменты для успеха Вашего бизнеса и увеличения вашей прибыли! Мы делаем красивые и максимально эффектные сайты по доступным ценам уже много лет!
Комплексный подход это не просто продвижение сайта, это целый комплекс мероприятий, который определяется целями и задачами поставленными перед сайтом и организацией, которая за этим стоит. Время однобоких методов в продвижении сайтов уже прошло, конкуренция слишком высока, чтобы была возможность расслабиться и получать \ удерживать клиентов из Интернета, просто сделав сайт и не занимаясь им...
Мы оказываем полный комплекс услуг по сопровождению сайта: информационному и техническому обслуживанию и развитию Интернет сайтов.
Контекстная реклама - это эффективный инструмент в интернет маркетинге, целью которого является увеличение продаж. Главный плюс контекстной рекламы заключается в том, что она работает избирательно.