Каков наилучший способ обработки нескольких типов разрешений? - PullRequest
19 голосов
/ 04 августа 2008

Я часто сталкиваюсь со следующим сценарием, где мне нужно предлагать много разных типов разрешений. Я в основном использую 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
    

Мои мысли

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

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

Ответы [ 5 ]

12 голосов
/ 04 августа 2008

Я согласен с Джоном Дауни.

Лично я иногда использую помеченное перечисление разрешений. Таким образом, вы можете использовать битовые операции 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).

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

9 голосов
/ 04 августа 2008

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

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

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

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

2 голосов
/ 07 августа 2008

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

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

2 голосов
/ 04 августа 2008

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

0 голосов
/ 04 августа 2008

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

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

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

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

...