Cho phép nhiều vai trò truy cập hành động của bộ điều khiển


274

Ngay bây giờ tôi trang trí một phương thức như thế này để cho phép "thành viên" truy cập hành động điều khiển của tôi

[Authorize(Roles="members")]

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

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

4
Hãy 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 được chấp nhận đã chỉnh sửa nó cho thấy anh ta đã sai.
Eric J.

Câu trả lời:


595

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

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

5
Hoạt động trong MVC 5 cũng vậy. +1
gkonuralp

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

3
Điều này là ổn nếu bạn chỉ có một bộ điều khiển mà bạn cần ủy quyền. Nếu bạn có nhiều hơn một, bạn đang sao chép các hằng chuỗi đó (yuck). Tôi rất thích lớp tĩnh có tên vai trò. Thú cưng của tôi ghét chuỗi trùng lặp ... rất tệ.
cướp

1
@kraeg tin tốt rằng bạn đã giải quyết vấn đề của bạn. Bây giờ, hãy cân nhắc xóa bình luận của bạn, làm ơn
Pablo Claus

1
Tại sao? Tôi mất nhiều thời gian để làm việc này. Nó có thể hữu ích cho người khác gặp vấn đề tương tự.
kraeg

128

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 học:

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

Sử dụng

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

Nếu bạn có một vài vai trò, có lẽ bạn có thể kết hợp chúng (cho rõ ràng) như thế này:

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

Sử dụng

[Authorize(Roles = CustomRoles.AdministratorOrUser)]

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

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 có chứa một số hằng, tương ứng với các 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 thay đổi vai trò, tôi phải cập nhật chỉ một nơi trong ứng dụng của mình.
Pablo Claus

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

Nếu bạn có 39 vai trò?
Kiquenet

Tôi nghĩ vấn đề của bạn là thông qua việc mô hình hóa các giấy phép vượt ra ngoài những gì có thể được thực hiện với .net
Pablo Claus

81

Một sự đơn giản hóa có thể là lớp con AuthorizeAttribute:

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

Sử dụng:

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

Về mặt ngữ nghĩa, nó giống như câu trả lời của Jim Schmehil.


3
Điều này không hiệu quả 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

8
Câu trả lời này tốt hơn khi bạn sử dụng các hằng số làm giá trị của mình: tức là [Vai trò (Hằng
số.Admin

2
đây là câu trả lời hay nhất
IgorShch

18

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

Về hành động 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 AuthorizeAttributenhư 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 FNHMVC được sửa đổi bởi Fabricio Martínez Tamayo https://github.com/foveniomrtnz/FNHMVC/


1
Phương pháp OnAuthorization của bạn sẽ yêu cầu người dùng có tất cả các vai trò liệt kê; đó là cố ý, hay bạn đang thiếu một khoảng nghỉ trong vòng lặp đó?
Tieson T.

@Tieson: Tôi đã kiểm tra khá kỹ, có vẻ như sẽ cần phải nghỉ trong vòng lặp đó.
OcelotXL

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

Các UserRoles enum là tốt đẹp. Bạn có khai báo thủ công hay nó được tự động phát triển dựa trên nội dung của DB?
Konrad Viltersten

@KonradViltersten Đó là thủ công nhưng tôi đoán với lớp Reflection và Dynamic có thể được tạo tự động
Bernardo Loureiro

3

Một giải pháp rõ ràng khác, bạn có thể sử dụng các hằng số để giữ quy ước và thêm nhiều thuộc tính [Ủy quyền]. Kiểm tra này:

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

14
Nhiều Authorizethuộc tính sử dụng VÀ ngữ nghĩa và yêu cầu TẤT CẢ các điều kiện phải được đáp ứng (nghĩa là người dùng phải ở cả hai vai trò Quản trị viên và Khách).
quần

3

Nếu bạn thấy mình áp dụng 2 vai trò đó thường xuyên, bạn có thể bọc chúng trong Ủy quyền của riêng họ. Đây thực sự là một 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ĩ rằng điều này có vẻ sạch hơn và đọc dễ dàng.

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

1

Mã 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 này

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

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

1

Sử dụng AspNetCore 2.x, bạn phải đi một cách khác:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)]
public class AuthorizeRoleAttribute : AuthorizeAttribute
{
    public AuthorizeRoleAttribute(params YourEnum[] roles)
    {
        Policy = string.Join(",", roles.Select(r => r.GetDescription()));
    }
}

chỉ sử dụng nó như thế này:

[Authorize(YourEnum.Role1, YourEnum.Role2)]

-2
Intent promptInstall = new Intent(android.content.Intent.ACTION_VIEW);
promptInstall.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
promptInstall.setDataAndType(Uri.parse("http://10.0.2.2:8081/MyAPPStore/apk/Teflouki.apk"), "application/vnd.android.package-archive" );

startActivity(promptInstall);

1
Các câu trả lời bao gồm mã phải có ít nhất một mô tả tối thiểu giải thích cách mã hoạt động và lý do tại sao nó trả lời cho câu hỏi. Hơn nữa việc định dạng phần mã cần được cải thiện.
Roberto Caboni

Huh? @Orsit Moel, Hình như bị sao chép vào chủ đề sai ...
Cameron Forward
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.