2009-03-31 4 views
176

Сейчас я декорировать метод, как это, чтобы «члены», чтобы получить доступ к моему контроллеру действиеРазрешить несколько ролей для доступа к действию контроллера

[Authorize(Roles="members")] 

Как разрешить более одной роли? Например, следующий не работает, но это показывает, что я пытаюсь сделать (разрешить «членов» и «админ» доступ):

[Authorize(Roles="members", "admin")] 
+4

Пожалуйста, измените принятый ответ на этот вопрос. Человек с принятым в настоящее время ответом отредактировал его, указав, что он ошибается. –

ответ

467

Другой вариант заключается в использовании одного Авторизоваться фильтра, как вы вывесили, но удалить внутренние цитаты.

[Authorize(Roles="members, admin")] 
+3

Работает в MVC3 и MVC4 +1 –

+4

Работает также в MVC 5. +1 – gkon

+4

Работает в ASP.NET Core 1.0 (MVC 6) и Microsoft.AspNet.Identity v3. * – Soren

91

Если вы хотите использовать пользовательские роли, вы можете сделать это:

CustomRoles класс:

public static class CustomRoles 
{ 
    public const string Administrator = "Administrador"; 
    public const string User = "Usuario"; 
} 

Использование

[Authorize(Roles = CustomRoles.Administrator +","+ CustomRoles.User)] 

Если у вас есть несколько ролей, может быть, вы можете объединить их (для ясности) следующим образом:

public static class CustomRoles 
{ 
    public const string Administrator = "Administrador"; 
    public const string User = "Usuario"; 
    public const string AdministratorOrUser = Administrator + "," + User; 
} 

Использование

[Authorize(Roles = CustomRoles.AdministratorOrUser)] 
+5

Это был бы хороший ответ, если бы вы объяснили людям, которые не знали, что стоит за CustomRoles. –

+1

@JamesSkemp ok, я расширил свой ответ. Это очень просто. CustumRoles - это класс, который я создал, который содержит некоторые константы, соответствующие моим ролям приложения. Я сделал это по нескольким причинам: 1) Это позволяет использовать intellisense, чтобы избежать орфографических ошибок. 2) Для упрощения обслуживания. Если изменение роли, я должен обновить только одно место в моем приложении. –

+0

@Pabloker В качестве альтернативы вы можете создать перечисление с атрибутом Flags, например. Convert.ToString (CustomRoles.Administrator | CustomRoles.User); - раздражающая часть заключается в том, что для этого требуется явное преобразование – cstruter

14

Для MVC4, используя Enum (UserRoles) со своими ролями, я использую пользовательский AuthorizeAttribute.

На моем контролированным действии, я:

[CustomAuthorize(UserRoles.Admin, UserRoles.User)] 
public ActionResult ChangePassword() 
{ 
    return View(); 
} 

И я использую обычай AuthorizeAttribute подобное:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
public class CustomAuthorize : AuthorizeAttribute 
{ 
    private string[] UserProfilesRequired { get; set; } 

    public CustomAuthorize(params object[] userProfilesRequired) 
    { 
     if (userProfilesRequired.Any(p => p.GetType().BaseType != typeof(Enum))) 
      throw new ArgumentException("userProfilesRequired"); 

     this.UserProfilesRequired = userProfilesRequired.Select(p => Enum.GetName(p.GetType(), p)).ToArray(); 
    } 

    public override void OnAuthorization(AuthorizationContext context) 
    { 
     bool authorized = false; 

     foreach (var role in this.UserProfilesRequired) 
      if (HttpContext.Current.User.IsInRole(role)) 
      { 
       authorized = true; 
       break; 
      } 

     if (!authorized) 
     { 
      var url = new UrlHelper(context.RequestContext); 
      var logonUrl = url.Action("Http", "Error", new { Id = 401, Area = "" }); 
      context.Result = new RedirectResult(logonUrl); 

      return; 
     } 
    } 
} 

Это является частью доработанного FNHMVC от Фабрисио Мартинеса Тамайо https://github.com/fabriciomrtnz/FNHMVC/

+1

. Ваш метод OnAuthorization потребует, чтобы пользователь имел ** все ** перечисленные роли; было ли это преднамеренным, или вам не хватает перерыва в этом цикле? –

+0

@Tieson: Я внимательно изучил, что определенно кажется, что в этом цикле потребуется перерыв. – OcelotXL

+0

@TiesonT. и @ madrush, я ценю ваше исправление, он действительно мог бы прорваться внутри цикла. Я изменю код выше. –

57

Одним из возможных упрощений будет подкласс AuthorizeAttribute:

public class RolesAttribute : AuthorizeAttribute 
{ 
    public RolesAttribute(params string[] roles) 
    { 
     Roles = String.Join(",", roles); 
    } 
} 

Использование:

[Roles("members", "admin")] 

Семантически это же, как и ответ Джима Schmehil в.

+1

Это не сработало для меня, зарегистрированный пользователь смог обойти этот атрибут, даже если у пользователя не было ни одной из ролей. – Urielzen

+2

Этот ответ лучше, когда вы используете константы в качестве своих значений: ie [Роли (Constants.Admin, Constants.Owner)] – user1191559

0

Лучше код с добавлением подкласса AuthorizeRole.cs

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
    class AuthorizeRoleAttribute : AuthorizeAttribute 
    { 
     public AuthorizeRoleAttribute(params Rolenames[] roles) 
     { 
      this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r))); 
     } 
     protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) 
     { 
      if (filterContext.HttpContext.Request.IsAuthenticated) 
      { 
       filterContext.Result = new RedirectToRouteResult(
       new RouteValueDictionary { 
        { "action", "Unauthorized" }, 
        { "controller", "Home" }, 
        { "area", "" } 
        } 
      ); 
       //base.HandleUnauthorizedRequest(filterContext); 
      } 
      else 
      { 
       filterContext.Result = new RedirectToRouteResult(
       new RouteValueDictionary { 
        { "action", "Login" }, 
        { "controller", "Account" }, 
        { "area", "" }, 
        { "returnUrl", HttpContext.Current.Request.Url } 
        } 
      ); 
      } 
     } 
    } 

Как пользоваться

[AuthorizeRole(Rolenames.Admin,Rolenames.Member)] 

public ActionResult Index() 
{ 
return View(); 
} 
1

другим прозрачным раствором, вы можете использовать константы, чтобы сохранить соглашение и добавить несколько [Авторизоваться] атрибуты.Проверьте это:

public static class RolesConvention 
{ 
    public const string Administrator = "Administrator"; 
    public const string Guest = "Guest"; 
} 

Тогда в контроллере:

[Authorize(Roles = RolesConvention.Administrator)] 
[Authorize(Roles = RolesConvention.Guest)] 
[Produces("application/json")] 
[Route("api/[controller]")] 
public class MyController : Controller 
+6

В нескольких атрибутах 'Authorize' используются AND семантика и требуются ВСЕ УСЛОВИЯ (т.е. пользователь должен быть в роли администратора и гостя). – trousyt

0

Если вы обнаружили, применяя эти 2 роли часто вы можете обернуть их в их собственном Авторизоваться. Это действительно расширение принятого ответа.

using System.Web.Mvc; 

public class AuthorizeAdminOrMember : AuthorizeAttribute 
{ 
    public AuthorizeAdminOrMember() 
    { 
     Roles = "members, admin"; 
    } 
} 

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

public class MyController : Controller 
{ 
    [AuthorizeAdminOrMember] 
    public ActionResult MyAction() 
    { 
     return null; 
    } 
} 
Смежные вопросы