Как лучше всего управлять разрешениями для веб-приложения - битовой маской или таблицей базы данных?

Я рассматриваю лучший способ разработать систему разрешений для «админского» веб-приложения. У приложения, вероятно, будет много пользователей, каждому из которых может быть назначена определенная роль; некоторым из этих пользователей может быть разрешено выполнять определенные задачи вне роли.

Я могу придумать два способа спроектировать это: первый, с таблицей «разрешений» со строкой для каждого пользователя и логическими столбцами, по одному для каждой задачи, которые назначают им разрешения для выполнения этих задач. Нравится:

User ID          Manage Users     Manage Products     Manage Promotions     Manage Orders
1                true             true                true                  true
2                false            true                true                  true
3                false            false               false                 true

Еще один способ, который я придумал, - это использовать битовую маску для хранения этих разрешений пользователей. Это ограничило бы количество задач, которыми можно было бы управлять, до 31 для 32-битного целого числа со знаком, но на практике у нас вряд ли будет более 31 конкретной задачи, которую может выполнить пользователь. Таким образом, схема базы данных будет проще, и нам не придется менять структуру таблицы каждый раз, когда мы добавляем новую задачу, для которой потребуется контроль доступа. Нравится:

User ID          Permissions (8-bit mask), would be ints in table
1                00001111
2                00000111
3                00000001

Какие механизмы здесь обычно используют люди и почему?

Спасибо!


person Hari    schedule 13.10.2008    source источник
comment
Используйте подход, основанный на политике, например ABAC   -  person David Brossard    schedule 27.03.2018


Ответы (9)


Я думаю, что это общее практическое правило - держаться подальше от мистических битовых строк, которые кодируют значение вселенной.

Хотя, возможно, более неудобно, но наличие таблицы возможных разрешений, таблицы пользователей и таблицы связей между ними - лучший и самый ясный способ организовать это. Это также значительно упрощает ваши запросы и обслуживание (особенно для новичка).

person Lucas Oman    schedule 13.10.2008
comment
Можете ли вы предоставить какую-либо существенную основу для общего практического правила, чтобы держаться подальше от мистических битовых строк. потому что я думал использовать битовую строку для разрешения. - person icanbeacoder; 07.11.2014
comment
Я использую этот подход в своих системах, и он отлично работает. Между таблицами правил и пользователей существует таблица связей, и каждый пользователь может быть назначен одному или нескольким правилам, и эти правила суммируются. Что касается комментария icanbeacoder, я думаю, что моделирование должно быть максимально вычитаемым. - person dellasavia; 20.01.2015
comment
Что ж, это не совсем самодокументируется, и я бы сказал, что это нарушает принцип наименьшего удивления. Он также хрупкий, он предполагает, что столбцы всегда идут в определенном порядке (я не администратор базы данных, но уверен, что это серьезный запрет-нет), и я готов поспорить, что было бы не очень весело редактировать устаревшую базу данных с помощью множество данных, реализующих эти загадочные байтовые строки, чтобы учесть такие вещи, как различные права администратора для разных линеек продуктов, разные типы пользователей или настроить правила для разных частей одной и той же компании. - person Erik Reppen; 04.02.2015
comment
Что ж, я, вероятно, не стал бы использовать для этого битовую маску, потому что мы не знаем заранее, сколько возможных разрешений может быть в будущем. Тем не менее, битовые маски не являются загадкой для реальных разработчиков программного обеспечения. Вот несколько ссылок для тех, кто хотел бы туда попасть: stu.mp/2004/06/a-quick-bitmask-howto-for-programmers.html stackoverflow.com/questions/141525/ - person Reversed Engineer; 27.01.2016
comment
Дело не в том, может ли разработчик понять, что такое битовая маска. Дело в том, может ли разработчик определить назначение каждого бита в конкретной битовой маске. Если вы не работаете над критически важным программным обеспечением, которое должно иметь чрезвычайно низкую задержку, ВСЕГДА лучше быть понятым, чем быть умным / быстрым. Если это не хобби-проект, в этом случае будьте настолько умны, насколько хотите, и удачи, пытаясь понять, о чем вы думали через год, когда вернетесь к нему :) - person Dave; 11.04.2017

как насчет создания таблицы разрешений, а затем таблицы UserPermission для хранения взаимосвязей?

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

person Levi Rosol    schedule 13.10.2008
comment
Это совершенно правильно. Если вы получите детализированные разрешения для многих модулей, вы потенциально можете получить сотни возможностей. Ни набор столбцов, ни битовая маска не понравятся в таком расположении, но ваша идея прекрасно масштабируется. - person Kirk Strauser; 14.10.2008

Я сделал это обоими способами. Но я больше не использую битовые маски. Подойдет отдельная таблица, которую вы можете использовать в качестве перекрестной ссылки, учитывая идентификатор пользователя или идентификатор группы в качестве внешнего ключа.

UserID | Permission
===================
1      | 1              1 representing manage users
1      | 2              2 being manger products
2      | 3 

Такой способ будет легче поддерживать и добавлять позже.

Я бы также использовал отдельную таблицу для управления разрешениями.

PermissionID | Description
==========================
1            | Manage Users
2            | Manager Products
person stephenbayer    schedule 13.10.2008

Обычно у меня есть таблица Users, таблица Roles и таблица UserRoles. Таким образом, у вас может быть неограниченное количество ролей без изменения структуры базы данных, а пользователи могут быть в нескольких ролях.

Я заставляю приложение авторизоваться только для ролей (а не для пользователей). Обратите внимание, что столбец «id» в таблице ролей не является столбцом идентификаторов. Это связано с тем, что вам может потребоваться контролировать идентификаторы, которые помещаются в эту таблицу, потому что вашему приложению придется искать определенные идентификаторы.

Структура выглядит так:

create table Users (
 id int identity not null,
 loginId varchar(30) not null,
 firstName varchar(50) not null,
 etc...
)

create table Roles (
 id int not null,
 name varchar(50) not null
)

create table UserRoles (
 userId int not null,
 roleId int not null
)
person Chad Braun-Duin    schedule 13.10.2008

Вы можете использовать Active Directory или другую реализацию LDAP, если вы находитесь в управляемой среде. Таким образом, группы безопасности, которые определяют разрешения, могут управляться службой поддержки первой линии с использованием технологии, с которой они, скорее всего, уже знакомы.

Если ваше приложение упаковано в термоусадочную пленку, то +1 за предложение Леви Росола о нормализации базы данных, чтобы вы могли иметь расширяемую модель данных в своем приложении.

person Ed Blackburn    schedule 10.04.2009

Я бы предложил абстрагировать разрешения вашего веб-приложения с помощью концепции поставщика ролей. Начиная с версии 2.0, это предоставляется в .NET как System.Web.Security.RoleProvider.

Основная идея состоит в том, что вы используете существующую структуру, записывая свои проверки разрешений в соответствии с ней, а не конкретным механизмом хранения. Затем вы можете подключить любой доступный механизм хранения, будь то XML-файл, база данных или даже хранилище авторизации с помощью диспетчера авторизации программного обеспечения Windows (который позволяет легко привязать свои пользовательские разрешения к LDAP, как один пример - код для настройки не требуется).

Если вы решите использовать базу данных в качестве механизма хранения, поддерживаются несколько баз данных для автоматического создания базовых таблиц, которые необходимы платформе. Это включает запуск .NET на Mono и использование модели поставщика ролей поверх MySQL.

Дополнительную информацию см. В разделе Реализация поставщика ролей. Вполне возможно, что в других языках / средах также есть библиотеки, которые вы могли бы использовать для реализации этой концепции - на это стоит обратить внимание.

РЕДАКТИРОВАТЬ: я также должен указать, что настройка того, как ваше веб-приложение связано с механизмом хранения, выполняется через файл web.config и не требует изменения кода. Я нашел это очень полезным для тестирования производственной версии кодовой базы на моем локальном компьютере с использованием XML-файла для имитации разрешений вместо обычного поставщика базы данных - и все это путем изменения двух строк в web.config.

Другая вещь, о которой я забыл упомянуть, это то, что вы можете подключать свои собственные пользовательские поставщики, расширяя базовые классы, что позволяет вам использовать модель разрешений, но при этом использовать проприетарную систему хранения (например, битовые маски, если вы действительно этого хотите) .

person J c    schedule 13.10.2008

Я видел несколько несколько ограниченных систем разрешений, подобных тому, что вы предлагаете, а также некоторые действительно ужасные системы. В некоторых простых ситуациях они могут быть приемлемыми, если приложение не становится более сложным. Однако во многих случаях они становятся более сложными, и системы необходимо переписывать, чтобы обеспечить необходимую функциональность.

Если вы думаете, что когда-нибудь вам может понадобиться выразительность, я бы выбрал систему полного ACL (списка контроля доступа) с пользователями и группами (или ролями). То есть каждая вещь, управляемая разрешениями (например, «управление пользователями», «управление продуктами»), имеет ACL, который представляет собой список всех пользователей и групп, имеющих к нему доступ. Затем пользователи либо добавляются непосредственно в соответствующие ACL, либо добавляются в группу, которая уже является членом ACL.

Хотя ACL предлагает реализацию списка, вам будет лучше с таблицей; этот ответ - хороший способ.

person TimB    schedule 13.10.2008

Не могу комментировать, потому что я новичок в SO, но что касается принятого ответа - огромное преимущество, которое дает это решение, - это возможность универсально обрабатывать разрешения, а не только операторы if повсюду в коде, а также специальные возможности например, временные разрешения (разрешения, срок действия которых истекает)

person Bobby Dawson    schedule 19.07.2019

Разрешения обычно представляют собой ключевые слова с 1, 0 или нулем (что указывает на наследование). С битовой системой вы, вероятно, не сможете создавать индексы по идентификатору пользователя и ключевому слову разрешения; вместо этого вам придется сканировать каждую запись, чтобы получить значение разрешения.

Я бы посоветовал выбрать первый вариант. Мне кажется, лучшее решение:

create table permissions (
    user_id INT NOT Null,
    permission VARCHAR(255) NOT NULL,
    value TINYINT(1) NULL
)
alter table `permissions` ADD PRIMARY KEY ( `user_id` , `permission` ) 
person Dimitry    schedule 13.10.2008
comment
Это заканчивается тем же самым разрешением, которое потенциально может быть определено тысячи раз. Таблица "многие ко многим" гораздо более масштабируема. - person Kirk Strauser; 14.10.2008
comment
Но у вас может быть разрешение CanChangePassword 100 000 раз для 100 000 уникальных пользователей. Вы действительно хотите хранить одну и ту же строку столько раз? - person Kirk Strauser; 14.10.2008