Каков наилучший способ обработки нескольких типов разрешений?

Я часто сталкиваюсь со следующим сценарием, где мне нужно предлагать много разных типов разрешений. Я в основном использую ASP.NET / VB.NET с SQL Server 2000.

сценарий

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

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

  1. Используйте одну таблицу разрешений со специальными столбцами, которые используются для определения того, как применять параметры. Специальными столбцами в этом примере являются TypeID и TypeAuxID. SQL будет выглядеть примерно так.

    SELECT COUNT(PermissionID)
    FROM application_permissions
    WHERE
    (TypeID = 1 AND TypeAuxID = @UserID) OR
    (TypeID = 2 AND TypeAuxID = @DepartmentID)
    AND ApplicationID = 1
    
  2. Используйте таблицу сопоставления для каждого типа разрешений, а затем объедините их все вместе.

    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 q.SectionID=@SectionID
      AND (emp.UserID=@UserID OR dept.DeptID=@DeptID OR
     (emp.UserID IS NULL AND dept.DeptID IS NULL)) AND ApplicationID = 1
    ORDER BY q.QID ASC
    

Мои мысли

Я надеюсь, что примеры имеют смысл. Я сделал их вместе.

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

4.08.2008 17:46:28
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).

Внутри вашего приложения вам просто нужна другая побитовая операция (ИЛИ), чтобы проверить, есть ли у пользователя определенное разрешение или нет.

13
4.08.2008 18:23:40
проблема, с которой я столкнулся при таком подходе, состоит в том, что с этим подходом действительно легко выйти из роли. Как видите, 6 ролей имеют значение 2 ^ 6 = 64, тогда как 31 роль будет иметь 2 ^ 31 = 2 147 483 647, что является максимальным значением int. Таким образом, в T-SQL самый большой тип данных, который можно использовать, это bigint(2 ^ 63). Конечно, вы можете использовать тип varchar, но я предпочитаю использовать решение Джона Дауни, когда у меня много ролей.
Maksim Vi. 7.10.2011 00:47:08

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

  • Пользователи - это довольно просто, это типичная таблица пользователей
  • Группы - это будет синонимом для ваших отделов
  • Роли - это таблица со всеми разрешениями, обычно также включающая удобочитаемое имя и описание
  • Users_have_Groups - это таблица «многие ко многим», к каким группам принадлежит пользователь
  • Users_have_Roles - еще одна таблица «многие ко многим» о том, какие роли назначены отдельному пользователю
  • Groups_have_Roles - окончательная таблица «многие ко многим» о ролях каждой группы

В начале сеанса пользователя вы запускаете некоторую логику, которая вытягивает каждую назначенную им роль, либо каталог, либо через группу. Затем вы кодируете эти роли как свои разрешения безопасности.

Как я уже говорил, это то, что я обычно делаю, но ваш опыт может варьироваться.

9
4.08.2008 17:56:26

В дополнение к решениям Джона Дауни и jdecuyper я также добавил бит «Явное запрещение» в конце / начале битового поля, чтобы вы могли выполнять аддитивные разрешения по группам, членству в ролях, а затем вычитать разрешения на основе явного отказа Записи, так же, как NTFS работает, с разрешения.

2
4.08.2008 18:39:56

Честно говоря, функции членства и ролей ASP.NET отлично подойдут для описанного вами сценария. Написание собственных таблиц / процедур / классов - отличное упражнение, и вы можете получить очень хороший контроль над мелкими деталями, но после этого я решил, что лучше просто использовать встроенный материал .NET. Многое из существующего кода предназначено для его обхода, и это хорошо. Написание с нуля заняло у меня около 2 недель, и это было далеко не так надежно, как .NET. Вы должны закодировать столько дерьма (восстановление пароля, автоматическая блокировка, шифрование, роли, интерфейс доступа, тонны процедур и т. Д.), И время лучше потратить в другом месте.

Извините, если я не ответил на ваш вопрос, я как парень, который говорит изучать c #, когда кто-то задает вопрос vb.

2
7.08.2008 02:23:18

Подход, который я использовал в различных приложениях, заключается в том, чтобы иметь общий класс PermissionToken, который имеет изменяемое свойство Value. Затем вы запрашиваете запрошенное приложение, оно сообщает вам, какие PermissionTokens необходимы для его использования.

Например, приложение Shipping может сообщить вам, что ему нужно:

new PermissionToken()
{
    Target = PermissionTokenTarget.Application,
    Action = PermissionTokenAction.View,
    Value = "ShippingApp"
};

Это, очевидно, может быть расширено на «Создание», «Редактирование», «Удаление» и т. Д., И, благодаря пользовательскому свойству «Значение», любое приложение, модуль или виджет могут определять свои собственные необходимые разрешения. YMMV, но это всегда был эффективный метод для меня, который я нашел, чтобы хорошо масштабироваться.

0
4.08.2008 18:03:57