2009-03-31 9 views
176

Ngay bây giờ tôi trang trí một phương pháp như thế này để cho phép "thành viên" để truy cập controller action tôiCho phép nhiều vai trò để truy cập điều khiển hành động

[Authorize(Roles="members")] 

Làm thế nào để cho phép nhiều hơn một vai trò? Ví dụ sau đây không làm việc nhưng nó cho thấy những gì tôi đang cố gắng để làm (cho phép "thành viên" và "admin" truy cập):

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

Vui lòng thay đổi câu trả lời được chấp nhận cho câu hỏi này. Người có câu trả lời hiện đang được chấp nhận đã chỉnh sửa câu trả lời cho biết rằng anh đã sai. –

Trả lời

467

Một lựa chọn khác là sử dụng một bộ lọc ủy quyền duy nhất là bạn được đăng nhưng loại bỏ các trích dẫn bên trong.

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

Hoạt động trong MVC3 và MVC4 +1 –

+4

Hoạt động trong MVC 5. +1 – gkon

+4

Hoạt động trong ASP.NET Core 1.0 (MVC 6) và Microsoft.AspNet.Identity v3. * – Soren

91

Nếu bạn muốn sử dụng vai trò tùy chỉnh, bạn có thể làm điều này:

CustomRoles lớp:

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

Cách sử dụng

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

Nếu bạn có vài vai diễn, có lẽ bạn có thể kết hợp chúng (để làm rõ) như sau:

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

Cách sử dụng

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

Đây sẽ là một câu trả lời hay, nếu bạn giải thích cho những người không biết những gì đằng sau CustomRoles. –

+1

@JamesSkemp ok, tôi đã mở rộng câu trả lời của mình. Nó rất đơn giản. CustumRoles là một lớp mà tôi tạo ra có chứa một số hằng số, tương ứng với vai trò ứng dụng của tôi. Tôi đã làm điều đó vì một vài lý do: 1) Nó cho phép sử dụng intelliSense để tránh lỗi chính tả 2) Để đơn giản hóa việc bảo trì. Nếu một vai trò thay đổi, tôi phải cập nhật chỉ một chỗ trong ứng dụng của tôi. –

+0

@Pabloker Hoặc bạn có thể tạo một enum với thuộc tính Flags, ví dụ: Convert.ToString (CustomRoles.Administrator | CustomRoles.User); - một phần khó chịu là điều này đòi hỏi một chuyển đổi rõ ràng – cstruter

14

Đối MVC4, sử dụng một Enum (UserRoles) với vai trò của tôi, tôi sử dụng một tùy chỉnh AuthorizeAttribute.

On hành động được kiểm soát của tôi, tôi làm:

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

Và tôi sử dụng một tùy chỉnh AuthorizeAttribute như thế:

[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; 
     } 
    } 
} 

Đây là một phần của modifed FNHMVC Fabricio Martínez Tamayo https://github.com/fabriciomrtnz/FNHMVC/

+1

Phương thức OnAuthorization của bạn sẽ yêu cầu người dùng có ** tất cả ** các vai trò được liệt kê; đó là cố ý, hoặc bạn đang bỏ lỡ một break trong vòng lặp đó? –

+0

@Tieson: Tôi đã kiểm tra khá chặt chẽ, nó chắc chắn có vẻ như một sự phá vỡ sẽ được yêu cầu trong vòng lặp đó. – OcelotXL

+0

@TiesonT. và @ madrush, tôi đánh giá cao sự sửa chữa của bạn, nó thực sự có thể có một break bên trong vòng lặp. Tôi sẽ thay đổi mã ở trên. –

57

Một cách đơn giản có thể là phân lớp AuthorizeAttribute:

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

Cách sử dụng:

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

Ngữ nghĩa nó cũng giống như câu trả lời Jim Schmehil của.

+1

Điều này không hiệu quả đối với tôi, người dùng đã đăng nhập có thể bỏ qua thuộc tính ngay cả khi người dùng không có bất kỳ vai trò nào. – Urielzen

+2

Câu trả lời này tốt hơn khi bạn sử dụng hằng số làm giá trị của mình: tức là [Roles (Constants.Admin, Constants.Owner)] – user1191559

0

đang tốt hơn với việc thêm một lớp con 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 } 
        } 
      ); 
      } 
     } 
    } 

Làm thế nào để sử dụng

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

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

Một giải pháp rõ ràng này, bạn có thể sử dụng các hằng số để giữ cho hội nghị và thêm nhiều [Duyệt] thuộc tính.Check this out:

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

Sau đó, trong bộ điều khiển:

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

Nhiều thuộc tính 'Authorize' sử dụng AND ngữ nghĩa và yêu cầu TẤT CẢ các điều kiện được đáp ứng (tức là người dùng phải trong cả vai trò Quản trị viên và Khách). – trousyt

0

Nếu bạn thấy mình áp dụng những 2 vai trò thường bạn có thể bọc chúng trong Authorize riêng của họ. Đây thực sự là phần mở rộng của câu trả lời được chấp nhận.

using System.Web.Mvc; 

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

Và sau đó áp dụng ủy quyền mới của bạn cho Hành động. Tôi nghĩ nó trông sạch hơn và dễ đọc hơn.

public class MyController : Controller 
{ 
    [AuthorizeAdminOrMember] 
    public ActionResult MyAction() 
    { 
     return null; 
    } 
}