Я хотел бы построить объектную модель «Пользователь» для типичного веб-приложения… однако я не могу решить, как лучше всего разработать объектную модель и систему ролей.
В основном я планирую иметь около 4 типов пользователей… которые будут соответствовать «ролям» пользователей в провайдере членства.
Эти типы будут: • Рабочий • Работодатель • Гость • Администратор
Супертип это: • Пользователь
Вдобавок - Пользователь иногда может быть как «работником», так и «работодателем».
Я хотел бы использовать поставщика ролей и членства MS и настроить пользовательский интерфейс навигации для ответа на роль пользователя.
У меня вопрос: Как мне лучше всего сделать этих пользователей гибкими (пользователь может быть работником или работодателем). Как мне выполнить процедуру входа / ролей?
(Я думаю о пользователе с фабрикой для объектов «Поведение» (поведение работника, поведение работодателя))
Для входа пользователя в систему… находит свою роль и преобразуется в ее подтип.
Так ли это надо делать?





Использование только концепции роли само по себе всегда оказывалось для меня адекватным. Он не обеспечивает достаточно низкую степень детализации для управления разрешениями. Например, у вас может быть рабочая роль и роль администратора, а затем в коде вы используете Principal.IsInRole («Admin»), чтобы проверить их роль, чтобы определить, могут ли они изменить какое-либо значение (например, зарплату). Потом кто-то передумает и говорит, что руководители могут менять зарплату, но при этом не являются администраторами. Теперь вам нужно изменить свою проверку доступа, чтобы добавить еще одну проверку ролей. Болезненно и рутинно.
Итак, что я делаю, это составляю список всех функций в приложении, а затем разрешаю их связать с ролью в базе данных. Проверки моего доступа выглядят как Principal.HasPermission («ИЗМЕНЕНИЕ ЗАПЛАТЫ»). Я загружаю разрешения пользователей в зависимости от роли, к которой они прикреплены при входе в систему. Таким образом, компания может создавать столько групп функций, сколько они хотят, и давать им имена. Затем их можно применить к любому пользователю.
Я создаю настраиваемый объект-принципал и присоединяю его к потоку, чтобы я мог использовать его в любом коде на протяжении всего жизненного цикла страницы. Этот объект содержит код для загрузки разрешений из базы данных и методы проверки разрешений.
Я обычно считаю, что «поставщики» в структуре хороши для небольшого класса приложений и не подходят для большинства потребностей. К тому времени, как вы закончите подчинять их своей воле, было бы проще просто написать это с нуля.
Честно говоря, это, вероятно, не очень хорошее решение, но оно может помочь родить некоторые другие идеи.
Мои роли - это все возможные комбинации разрешений:
Worker, Employee, Guest, Admin, WorkerEmployee, etc
В моем коде у меня есть перечисление для отдельных разрешений
[Flags]
public enum RolePermissions
{
Guest = 1,
Worker = 2,
Employee = 4,
Admin = 8
}
и у меня есть перечисление, соответствующее ролям в базе данных. Целочисленные значения представляют собой побитовое ИЛИ разрешений:
public enum AvailableRoles
{
None = 0,
Guest = RolePermissions.Guest, //1
Worker = RolePermissions.Worker, // 2
Employee = RolePermissions.Employee, // 4
WorkerEmployee = RolePermissions.Worker | RolePermissions.Employee, // 6
Admin = RolePermissions.Admin, // 8
}
Затем есть набор методов, которые я могу использовать для поиска разрешений и прочего:
// Used to determine if the currently logged in user has a particular permission (Guest, Worker, Employee, Admin)
public static bool UserHasPermission( RolePermissions rolePermssion )
{
foreach( string role in Roles.GetRolesForUser() )
{
AvailableRoles availableRole = Parse( role );
if ( ( (RolePermissions)availableRole & rolePermssion ) == rolePermssion )
return true;
}
return false;
}
// Used to determine whether the currently logged in user is in a specific role
public static bool UserIsInRole( AvailableRoles requestedRole )
{
return UserIsInRole( Membership.GetUser().UserName, requestedRole );
}
// Used to determine whether a specific user is in a specific role
public static bool UserIsInRole( string username, AvailableRoles requestedRole )
{
foreach( string role in Roles.GetRolesForUser( username ) )
{
AvailableRoles actualRole = Parse( role );
if ( actualRole == requestedRole )
return true;
}
return false;
}
// Helper method to parse enum
private static AvailableRoles Parse( string role )
{
return (AvailableRoles)Enum.Parse( typeof( AvailableRoles ), role );
}
Если вы предложите лучший метод или внесете улучшения, дайте мне знать, чтобы я мог снова включить его в свой код. :-)