Как лучше всего обрабатывать несколько типов разрешений?
Я часто сталкиваюсь со следующим сценарием, когда мне нужно предложить много разных типов разрешений. В основном я использую ASP.NET / VB.NET с SQL Server 2000.
Сценарий
Я хочу предложить систему динамических разрешений, которая может работать с разными параметрами. Допустим, я хочу предоставить доступ к приложению отделу или только конкретному человеку. И представьте, что у нас есть ряд приложений, которые продолжают расти.
В прошлом я выбрал один из двух известных мне способов сделать это.
Используйте единую таблицу разрешений со специальными столбцами, которые используются для определения того, как применять параметры. Специальными столбцами в этом примере являются
TypeID
иTypeAuxID
. SQL будет выглядеть примерно так.SELECT COUNT(PermissionID) FROM application_permissions WHERE (TypeID = 1 AND TypeAuxID = @UserID) OR (TypeID = 2 AND TypeAuxID = @DepartmentID) AND ApplicationID = 1
Используйте таблицу сопоставления для каждого типа разрешений, а затем объедините их все вместе.
SELECT COUNT(perm.PermissionID) FROM application_permissions perm LEFT JOIN application_UserPermissions emp ON perm.ApplicationID = emp.ApplicationID LEFT JOIN application_DepartmentPermissions dept ON perm.ApplicationID = dept.ApplicationID WHERE [email protected] AND ([email protected] OR [email protected] OR (emp.UserID IS NULL AND dept.DeptID IS NULL)) AND ApplicationID = 1 ORDER BY q.QID ASC
Мои мысли
Я надеюсь, что эти примеры имеют смысл. Я сколотил их вместе.
Первый пример требует меньше усилий, но ни один из них не кажется лучшим ответом. Есть ли лучший способ справиться с этим?
Ответов (5)5
Я согласен с Джоном Дауни.
Лично я иногда использую помеченное перечисление разрешений. Таким образом, вы можете использовать побитовые операции AND, OR, NOT и XOR над элементами перечисления.
"[Flags]
public enum Permission
{
VIEWUSERS = 1, // 2^0 // 0000 0001
EDITUSERS = 2, // 2^1 // 0000 0010
VIEWPRODUCTS = 4, // 2^2 // 0000 0100
EDITPRODUCTS = 8, // 2^3 // 0000 1000
VIEWCLIENTS = 16, // 2^4 // 0001 0000
EDITCLIENTS = 32, // 2^5 // 0010 0000
DELETECLIENTS = 64, // 2^6 // 0100 0000
}"
Затем вы можете объединить несколько разрешений с помощью побитового оператора AND.
Например, если пользователь может просматривать и редактировать пользователей, двоичный результат операции - 0000 0011, который преобразован в десятичное число - 3.
Затем вы можете сохранить разрешение одного пользователя в одном столбце вашей базы данных (в нашем случае это будет быть 3).
Внутри вашего приложения вам просто нужна другая побитовая операция (ИЛИ), чтобы проверить, есть ли у пользователя конкретное разрешение или нет.
Подход, который я использовал в различных приложениях, состоит в том, чтобы иметь общий класс PermissionToken с изменяемым свойством Value. Затем вы запрашиваете запрошенное приложение, оно сообщает вам, какие PermissionTokens необходимы для его использования.
Например, приложение Доставка может сказать вам, что ему нужны:
new PermissionToken()
{
Target = PermissionTokenTarget.Application,
Action = PermissionTokenAction.View,
Value = "ShippingApp"
};
Это, очевидно, может быть расширено до Create, Edit, Delete и т. Д., И благодаря настраиваемому свойству Value любое приложение, модуль или виджет может определять свои собственные необходимые разрешения. YMMV, но для меня это всегда был эффективный метод, который, как я обнаружил, хорошо масштабируется.
Я обычно использую системы разрешений для кодирования с 6 таблицами.
- Пользователи - это довольно просто, это ваша типичная таблица пользователей
- Группы - это будет синонимом ваших отделов
- Роли - это таблица со всеми разрешениями, как правило, также включая удобочитаемое имя и описание.
- Users_have_Groups - это таблица "многие ко многим", к каким группам принадлежит пользователь.
- Users_have_Roles - еще одна таблица "многие ко многим", в которой указаны роли, назначенные отдельному пользователю.
- Groups_have_Roles - итоговая таблица "многие ко многим" с указанием ролей каждой группы.
В начале пользовательского сеанса вы должны запустить некоторую логику, которая извлекает каждую роль, которую они назначили, либо через каталог, либо через группу. Затем вы кодируете эти роли в качестве разрешений безопасности.
Как я уже сказал, это то, что я обычно делаю, но ваш стиль может отличаться.
Честно говоря, функции членства / ролей ASP.NET идеально подходят для описанного вами сценария. Написание собственных таблиц / процедур / классов - отличное упражнение, и вы можете получить очень хороший контроль над мельчайшими деталями, но, сделав это сам, я пришел к выводу, что лучше просто использовать встроенные в .NET вещи. Большая часть существующего кода предназначена для обхода этого, что хорошо получается. Написание с нуля заняло у меня около 2 недель, и это было далеко не так надежно, как .NET. Вам нужно кодировать так много чуши (восстановление пароля, автоматическая блокировка, шифрование, роли, интерфейс разрешений, множество процедур и т. Д.), И время можно было бы лучше потратить в другом месте.
Извините, если я не ответил на ваш вопрос, я похож на парня, который говорит изучать C#, когда кто-то задает вопрос vb.