Я начал разрабатывать приложение для форума в PHP на моей MVC Framework, и у меня есть этап, на котором я назначаю полномочия для членов (например: READ, WRITE, UPDATE, DELETE).
Теперь я знаю, что могу добавить 5 столбцов под пользовательской таблицей в моей базе данных и установить их в 1 | 0, но мне кажется, что слишком много, если я хочу добавить другие правила, например, MOVE.
И как я могу динамически назначать эти привилегии пользователям самостоятельно?
Я слышал о том, как использовать битмаски, но было бы очень хорошо, если бы я смог их полностью понять, прежде чем продолжить.
У вас есть пример того, как я могу это реализовать?
Описанный вами метод – индивидуальные привилегии, хранящиеся в столбцах, – это просто за счет гибкости (как вы заметили).
Метод Зуула еще более прост и по существу тот же, что и у вас, за исключением того, что он избегает необходимости в каких-либо утверждениях «ALTER TABLE». Тем не менее, это не нормируется, не легко запрашивается, а не самодокументируется.
Еще одна проблема с обоими этими методами заключается в том, что по мере роста вашей базы пользователей вы обнаружите, что все больше больно, чтобы все привилегии пользователя были установлены правильно. Вы окажетесь с большим количеством пользователей, которым нужны те же привилегии. Тем не менее, чтобы изменить привилегии пользователя, например, для размещения новой привилегии, вам нужно будет войти и добавить эту привилегию каждому пользователю, который нуждается в ней по отдельности. Майор ПИТА.
Для форума маловероятно, что вам понадобится управление привилегиями для каждого пользователя. Скорее всего, у вас будут определенные классы пользователей, такие как анонимные пользователи, зарегистрированные пользователи, модераторы, администраторы и т. Д. Это сделает его подходящим для управления доступом на основе ролей (RBAC). В этой системе вы должны назначить каждого пользователя роли и предоставить привилегии этой роли. Привилегии будут храниться как строки в таблице «привилегии». поэтому упрощенная схема базы данных будет выглядеть так:
PRIVILEGE int id (primary key) varchar description ROLE_PRIVILEGE_JOIN privilege_id (foreign key) role_id (foreign key) ROLE int id (primary key) varchar description USER int id (primary key) int role_id (foreign key)
Этот шаблон используется во многих приложениях, которые имеют дело с привилегиями пользователя. Добавьте все привилегии, которые любой мог бы иметь в виде строки в таблице привилегий; добавьте каждую роль, которую любой пользователь мог бы иметь в таблице ролей; и соответствующим образом свяжите их в таблице role_privilege_join.
Единственным реальным недостатком является то, что, поскольку используется таблица соединений, запрос «can user X do Y» будет несколько медленнее.
Бит-маска разрешений лучше всего понимать, если она представлена как двоичная, причем каждая цифра представляет собой разрешение, которое включено или выключено. Поэтому, если существуют разрешения X, Y и Z, и у меня есть только доступ к X и Z, 101
будет представлять, что у меня есть первая и третья разрешения, предоставленные мне, но не вторая. Двоичный номер 101
эквивалентен десятичному числу 5
, так что это то, что в конечном итоге будет сохранено в базе данных. Единственное маленькое целое число – гораздо более эффективный объект для хранения, чем строка или несколько небольших целых чисел.
EDIT: Я понял, насколько легко было использовать существующие функции преобразования, чтобы получить довольно быструю реализацию. Вот пример.
<?php function bitmask_expand($n) { // 9 returns array(1, 0, 0, 1) return str_split(base_convert($n, 10, 2)); } function bitmask_compact($a) { // array(1, 0, 0, 1) returns 9 return (int) base_convert(implode($a), 2, 10); } $ns = range(0, 7); foreach($ns as $n) { print_r($b = bitmask_expand($n)); echo bitmask_compact($b), "\n\n"; }
Вы можете получить более высокую производительность, если используете циклы, вместо того, чтобы тянуть назад и обратно от строк, но это довольно ясно иллюстрирует принцип.
Я бы создал таблицу под названием «Роли»:
CREATE TABLE Roles( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY(id), rolename VARCHAR(30))
Придерживайтесь всех необходимых разрешений. Затем создайте таблицу под названием «UserRoles», чтобы связать пользователей с ролями:
CREATE TABLE UserRoles( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY(id), UserId INT, RoleID INT)
Большая гибкость и простота в использовании (например, рабочий процесс, правила и т. Д.) (Я бы добавил и внешние ключи)
Вам не нужно усложнять это, просто используйте поле «ex: permissions» и сделайте что-то вроде:
$ permissions = "1; 1; 0; 1";
где в вашей озабоченности говорится:
READ – 1 (может)
WRITE – 1 (может)
UPDATE – 0 (не может)
DELETE – 1 (может)
тогда, проверяя, просто используйте «explode» by «;» …
Таким образом, вы всегда можете применять больше типов разрешений без изменения таблицы … таким образом, вы уменьшаете таблицу и ваш запрос быстрее!
Это решение для вашей проблемы 🙂