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

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

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

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

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

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

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

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

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

    Это, очевидно, может быть расширено для создания, редактирования, удаления и т.д., и, из-за свойства custom Value, любое приложение, модуль или виджет может определить свои собственные необходимые разрешения. YMMV, но это всегда был эффективный метод для меня, который я нашел для масштабирования хорошо.

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

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

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

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

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

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