asp.net mvc decorate с несколькими enumsми
У меня есть controller, и я хочу, чтобы две роли имели к нему доступ. 1-админ ИЛИ 2-замедлитель
Я знаю, что вы можете сделать [Authorize (Roles = “admin, moderators”)], но у меня есть свои роли в перечислении. С перечислением я могу разрешать только одну роль. Я не могу понять, как разрешить два.
Я пробовал что-то вроде [Authorize (Roles = MyEnum.Admin, MyEnum.Moderator)], но это не скомпилируется.
- Просмотры в отдельных assemblyх в ASP.NET MVC
- Экспорт в Excel в Asp.net MVC
- Как я могу переопределить шаблон @ Html.LabelFor?
- Добавление подкаталога в папку «View / Shared» в ASP.Net MVC и вызов представления
- Контекстное меню для добавления controllerа / просмотра отсутствует
Кто-то однажды предложил это:
[Authorize(Roles=MyEnum.Admin)] [Authorize(MyEnum.Moderator)] public ActionResult myAction() { }
но он не работает как OR. Я думаю, что в этом случае пользователь должен быть частью роли BOTH. Могу ли я игнорировать некоторый синтаксис? Или это случай, когда мне приходится отказываться от собственного пользовательского разрешения?
- Первая архитектура ASP.NET MVC3 и Entity Framework Code
- Для чего нужны файлы Web.Debug.config и Web.Release.Config?
- Получить дополнительные данные из структуры MVC5. Поставщик идентификации OAuth / OWin с внешним поставщиком авторизации
- ASP.NET MVC, Url Routing: максимальная длина пути (URL)
- Как визуализировать DateTime в определенном формате в ASP.NET MVC 3?
- Проверка объекта на основе внешних факторов (т. Е. Уникальность хранилища данных)
- Как я могу иметь строчные маршруты в ASP.NET MVC?
- Как издеваться над запросом на controller в ASP.Net MVC?
Попробуйте использовать оператор bit OR следующим образом:
[Authorize(Roles= MyEnum.Admin | MyEnum.Moderator)] public ActionResult myAction() { }
Если это не сработает, вы можете просто свернуть свое. Я только что сделал это в своем проекте. Вот что я сделал:
public class AuthWhereRole : AuthorizeAttribute { /// /// Add the allowed roles to this property. /// public UserRole Is; /// /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. /// /// /// protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException("httpContext"); // Make sure the user is authenticated. if (!httpContext.User.Identity.IsAuthenticated) return false; UserRole role = someUser.Role; // Load the user's role here // Perform a bitwise operation to see if the user's role // is in the passed in role values. if (Is != 0 && ((Is & role) != role)) return false; return true; } } // Example Use [AuthWhereRole(Is=MyEnum.Admin|MyEnum.Newbie)] public ActionResult Test() {}
Кроме того, обязательно добавьте атрибут flags в свой список и убедитесь, что все они оценены с 1 и выше. Как это:
[Flags] public enum Roles { Admin = 1, Moderator = 1 << 1, Newbie = 1 << 2 etc... }
Левое смещение битов дает значения 1, 2, 4, 8, 16 и так далее.
Надеюсь, это немного поможет.
Вот простое и элегантное решение, которое позволяет просто использовать следующий синтаксис:
[AuthorizeRoles(MyEnum.Admin, MyEnum.Moderator)]
Создавая свой собственный атрибут, используйте ключевое слово params
в своем конструкторе:
public class AuthorizeRoles : AuthorizeAttribute { public AuthorizeRoles(params MyEnum[] roles) { ... } protected override bool AuthorizeCore(HttpContextBase httpContext) { ... } }
Это позволит вам использовать атрибут следующим образом:
[AuthorizeRoles(MyEnum.Admin, MyEnum.Moderator)] public ActionResult myAction() { }
Я объединил несколько решений здесь, чтобы создать свой личный фаворит. Мой пользовательский атрибут просто изменяет данные в форме, которую ожидает SimpleMembership, и позволяет обрабатывать все остальное.
Мои роли перечислены:
public enum MyRoles { Admin, User, }
Чтобы создать роли:
public static void CreateDefaultRoles() { foreach (var role in Enum.GetNames(typeof(MyRoles))) { if (!Roles.RoleExists(role)) { Roles.CreateRole(role); } } }
Пользовательский атрибут:
public class AuthorizeRolesAttribute : AuthorizeAttribute { public AuthorizeRolesAttribute(params MyRoles[] allowedRoles) { var allowedRolesAsStrings = allowedRoles.Select(x => Enum.GetName(typeof(MyRoles), x)); Roles = string.Join(",", allowedRolesAsStrings); } }
Используется так:
[AuthorizeRoles(MyRoles.Admin, MyRoles.User)] public ActionResult MyAction() { return View(); }
Пытаться
public class CustomAuthorize : AuthorizeAttribute { public enum Role { DomainName_My_Group_Name, DomainName_My_Other_Group_Name } public CustomAuthorize(params Role[] DomainRoles) { foreach (var domainRole in DomainRoles) { var domain = domainRole.ToString().Split('_')[0] + "_"; var role = domainRole.ToString().Replace(domain, "").Replace("_", " "); domain=domain.Replace("_", "\\"); Roles += ", " + domain + role; } Roles = Roles.Substring(2); } } public class HomeController : Controller { [CustomAuthorize(Role.DomainName_My_Group_Name, Role.DomainName_My_Other_Group_Name)] public ActionResult Index() { return View(); } }
Вот моя версия, основанная на ответах @CalebHC и @Lee Harold.
Я придерживался стиля использования именованных параметров в атрибуте и переопределял свойство Roles
базовых classов.
@ Ответ CalebHC использует новое свойство Is
которое, как мне кажется, не нужно, потому что AuthorizeCore()
переопределяется (который в базовом classе использует роли), поэтому имеет смысл использовать наши собственные Roles
. Используя наши собственные Roles
мы получаем, чтобы написать Roles = Roles.Admin
на controllerе, который следует за стилем других атрибутов .Net.
Я использовал два конструктора для CustomAuthorizeAttribute
чтобы отображать имена реальных активных групп каталогов. В производстве я использую параметризованный конструктор, чтобы избежать магических строк в classе: имена групп вытягиваются из web.config во время Application_Start()
и передаются в создание с использованием инструмента DI.
Вам понадобится NotAuthorized.cshtml
или подобное в вашей папке Views\Shared
или неавторизованные пользователи получат экран с ошибкой.
Вот код для базового classа AuthorizationAttribute.cs .
controller:
public ActionResult Index() { return this.View(); } [CustomAuthorize(Roles = Roles.Admin)] public ActionResult About() { return this.View(); }
CustomAuthorizeAttribute:
// The left bit shifting gives the values 1, 2, 4, 8, 16 and so on. [Flags] public enum Roles { Admin = 1, User = 1 << 1 } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class CustomAuthorizeAttribute : AuthorizeAttribute { private readonly string adminGroupName; private readonly string userGroupName; public CustomAuthorizeAttribute() : this("Domain Admins", "Domain Users") { } private CustomAuthorizeAttribute(string adminGroupName, string userGroupName) { this.adminGroupName = adminGroupName; this.userGroupName = userGroupName; } /// /// Gets or sets the allowed roles. /// public new Roles Roles { get; set; } /// /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. /// /// The HTTP context. /// [True] if the user is authenticated and has the correct role /// /// This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method. /// protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } if (!httpContext.User.Identity.IsAuthenticated) { return false; } var usersRoles = this.GetUsersRoles(httpContext.User); return this.Roles == 0 || usersRoles.Any(role => (this.Roles & role) == role); } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } filterContext.Result = new ViewResult { ViewName = "NotAuthorized" }; } private IEnumerable GetUsersRoles(IPrincipal principal) { var roles = new List (); if (principal.IsInRole(this.adminGroupName)) { roles.Add(Roles.Admin); } if (principal.IsInRole(this.userGroupName)) { roles.Add(Roles.User); } return roles; } }
Чтобы добавить код CalebHC и ответить на вопрос ssmith о работе с пользователями, имеющими несколько ролей …
Наш пользовательский принцип безопасности возвращает массив строк, представляющий все группы / роли, в которых находится пользователь. Поэтому сначала мы должны преобразовать все строки в массиве, соответствующие элементам enums. Наконец, мы ищем любое совпадение – если да, то пользователь авторизован.
Обратите внимание, что мы также перенаправляем неавторизованного пользователя в пользовательский вид «NotAuthorized».
Весь class выглядит следующим образом:
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class CustomAuthorizeAttribute : AuthorizeAttribute { /// /// Add the allowed roles to this property. /// public Roles Is { get; set; } /// /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. /// /// /// protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException("httpContext"); if (!httpContext.User.Identity.IsAuthenticated) return false; var iCustomPrincipal = (ICustomPrincipal) httpContext.User; var roles = iCustomPrincipal.CustomIdentity .GetGroups() .Select(s => Enum.Parse(typeof (Roles), s)) .ToArray(); if (Is != 0 && !roles.Cast().Any(role => ((Is & role) == role))) { return false; } return true; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext == null) throw new ArgumentNullException("filterContext"); filterContext.Result = new ViewResult { ViewName = "NotAuthorized" }; } }
Или вы можете объединиться, как:
[Авторизовать (Роли = Common.Lookup.Item.SecurityRole.Administrator + “,” + Common.Lookup.Item.SecurityRole.Intake)]