нужно некоторое представление о том, как управлять ролями в моем приложении (ASP.NET MVC3)
Я разрабатываю сайт, который является своего рода онлайн-работе, там будут какие-то пользователи и некоторые постоянные Программирование проектов, и каждый пользователь может иметь несколько ролей, например, один конкретный пользователь может быть проект менеджер проекта и разработчик другого проекта. естественно, руководитель проекта имеет больше полномочий, чем разработчик в проекте. мой вопрос в том, как аккуратно управлять этим в моем коде? Я собирался использовать свой пользовательский поставщик ролей и использовать Авторизовать атрибут с этим, но этого недостаточно, так как мне нужен идентификатор проекта плюс идентификатор пользователя, чтобы найти роль пользователя в конкретном проекте.
7 ответов
сначала вам нужно будет создать дополнительные таблицы для расширенного управления ролями, такие как projects
а там отношения с users
в контексте operations
, который может быть вашим controller's actions
.
один из способов сделать это, чтобы создать свой собственный стол для roles
. В этом случае вы будете использовать только asp net membership users
, но все зависит от ваших требований.
во-вторых, вы должны справиться с этим в MVC
, на мой взгляд лучший способ-это реализовать через свой собственный Authorization
атрибут, и украсить действия вашего контроллера с помощью пользовательского атрибута авторизации вместо .
это очень просто.
[CustomAuthorize]
//[Authorize]
public ActionResult GetProjectTasks(string projectname)
{
}
для этого Вам должен присущ ваш класс от FilterAttribute
а также для реализации IAuthorizationFilter
интерфейс.
public void OnAuthorization(AuthorizationContext filterContext)
{
HttpCookie authCookie = filterContext.HttpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
if (authCookie != null)
{
FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);
var identity = new GenericIdentity(authTicket.Name, "Forms");
var principal = new GenericPrincipal(identity, new string[] { authTicket.UserData });
filterContext.HttpContext.User = principal;
}
var controller = filterContext.ActionDescriptor.ControllerDescriptor.ControllerName;
var action = filterContext.ActionDescriptor.ActionName;
var user = filterContext.HttpContext.User;
var ip = filterContext.HttpContext.Request.UserHostAddress;
var isAccessAllowed = CustomAuthenticationLogic.IsAccessAllowed(controller, action, user, ip);
if (!isAccessAllowed)
{
// Code if user is authenticated
FormsAuthentication.RedirectToLoginPage();
}
}
в методе OnAuthorization
, вы можете получить всю информацию, которая может потребоваться в пользовательскую логику авторизации как HttpContext
, Controller
имя, Action
имя. Вы должны просто вызвать свою пользовательскую логику аутентификации из этого метода.
Пользовательская логика проверки подлинности может выглядеть следующим образом.
public class CustomAuthenticationLogic
{
public static bool IsAccessAllowed(string controller, string action, IPrincipal user, string ip)
{
//
// Your custom logic here
//
}
}
Я сделал некоторое исследование некоторое время назад и могу заверить вас:
- ASP.NET встроенные функции, скорее всего, не помогут (нет никакого способа принять во внимание такие вещи, как project Id)
- модель доступа на основе ролей наиболее подходит, существуют различные способы ее реализации. Азман, предложенный Rusted, на самом деле хорош, но управление правилами, связанными с контекстом, может быть сложным. Например: пользователь A выполняет операцию B в проекте C, в то время как его позволяет сказать воскресенье. Взгляните на Азман.
- смешивание правил доступа с кодом крайне плохо. Ваша модель безопасности не должна быть связана с тем, как работает приложение (ASP.NET MVC) так что это неправильно:
var isAllowed = AccessControl.IsAccessAllowed(controller, action, user, ip);
это должно выглядеть так:
var isAllowed = AccessControl.IsAccessAllowed(user, operation, context);
затем вы можете использовать его, когда захотите, в каждом действии или обернуть его как атрибут.
где операция "войти", "отправить ответ", "Читать темы" и т. д. контекст-это все остальное, как вы "идентификатор проекта", " день недели", "user ip", etc
есть много вещей, которые могут быть написаны, например, перекрытие ролей, контекст и т. д. Короче говоря: Google для "модели доступа на основе ролей .NET", вероятно, может быть проще написать небольшую пользовательскую структуру безопасности. Заставьте его работать с пользователями, ролями, операциями и идентификатором проекта
ролям назначаются операции, Роли назначаются пользователям с определенным идентификатором проекта, вы можете жестко кодировать операции и роли, поэтому в вашей БД будет только одно небольшое изменение: пользователь на роли отображение
Если у вас есть более сложные правила и недостаточно атрибутов, вы можете вычислить в своем контроллере, может ли пользователь получить доступ к некоторым функциям и добавить свойства в ViewModel, которые отражают доступ или нет доступа к этим функциям.
таким образом, ваше представление будет очень тонким, оно будет отображать материал в зависимости от этих логических свойств ViewModel.
Итак, представляя, что ваш пользователь может только читать, вы можете иметь свойство bool IsReadOnly, которое будет заполняться в контроллер, в зависимости от правил авторизации, и который будет использоваться в представлении, например, для создания меток вместо текстовых полей.
Мне нравится основная идея: с Асман - это концепция программирования против операции.
операции очень гранулированные вещи, которые не должны иметь перекрытия в использовании и определяются только разработчиком. Группируя операции в задачи и задачи в роли, а затем сопоставляя участников (пользователей и группы) с ролями, вы получаете очень мощную модель для определения авторизации в приложении. Поскольку вы программируете непосредственно на операции, вашему коду не нужно какие роли у пользователя и которые могут быть изменены администратором во время выполнения. Фактически, кто-то может определить совершенно другой набор ролей для использования операций, которые вы используете в своем коде, и вам вообще не нужно будет менять код. Вот где настоящая сила.
Я не имею в виду" использовать AzMan в вашем приложении " (но, возможно, вам стоит попробовать). Это мощная модель, но она также сложна и, вероятно, чрезмерна для простых вещей. Если у вас есть роль или две и операции, которые они защищают, не перекрываются или вряд ли изменятся, тогда это вероятно, это не оправдано.
вы можете groups
на основе roles
.
затем добавьте разных пользователей в определенные группы. Группы могут быть >
1) Admin Group
2) Developer Group
3) Project1-QA Group
4) Project2-Manager Group
сохранить отображение [user - group]
и [group - projects]
в зависимости от дизайна вашей базы данных.
вы можете иметь столько ролей(групп) для одного пользователя, как вы хотите.
очень простой подход-для управления доступом по всему сайту вы можете добавить столбец INT в таблицу пользователя и сопоставить каждый бит этого INT с [flags]
перечисление - например,[Flags] enum Access { UpdateProjects, AddProjects }
.
для управления доступом для каждого проекта создайте таблицу с именем, например, ProjectAccessControl с тремя столбцами: ProjectID (внешний ключ к таблице проекта), UserID (внешний ключ к таблице пользователя) и Role (INT). Столбец роли является INT, и каждый его бит должен означать другой логический флаг (как и в предыдущем примере, вы можете сопоставьте это с перечислением в C#) и скажите, что если первый бит включен, то у пользователя есть права на обновление описания, если второй бит включен, пользователь может изменить расписание и так далее.
[Flags]
enum ProjectAccessRole
{
UpdateDescription,
ChangeSchedule,
etc...
}
в коде вы можете проверить, имеет ли роль пользователя право обновлять расписание таким образом:
if( (intUserRole & ProjectAccessRole.ChangeSchedule)
== ProjectAccessRole.ChangeSchedule)
{
/*user has right*/
}
затем вы можете обернуть эту проверку в простую функцию, которая принимает два параметра: 1) роль, которая должна быть проверена, если она есть 2) роль. Тогда вы просто позвоните HasRights(intUserRole, ProjectAccessRole.ChangeSchedule);
.