2008-08-04 5 views
17

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

Мои мысли

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

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

ответ

10

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

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

Затем вы можете комбинировать несколько разрешений с помощью побитового оператора И.

Например, если пользователь может просматривать & редактировать пользователей, бинарный результат операции 0000 0011 которая преобразуется в десятичное 3.
Вы можете хранить разрешение одного пользователя в одном столбце вашей базы данных (в нашем случае это будет 3).

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

+1

Проблема, с которой я столкнулся с этим подходом, состоит в том, что с помощью этого подхода очень просто выполнить определенные роли. Как видите, 6 ролей имеют значение 2^6 = 64, когда 31 ролей будет иметь 2^31 = 2,147,483,647, что является максимальным значением int. Таким образом, в T-SQL самым большим типом данных, который можно использовать, является `bigint` (2^63). Конечно, вы можете использовать тип varchar, но я предпочитаю использовать решение Джона Дауни, когда у меня много ролей. – 2011-10-07 00:47:08

10

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

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

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

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

0

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

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

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

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

2

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

2

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

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