Denetleyici eylemine erişmek için birden fazla rol izin ver


274

Şu anda "üyeler" in denetleyici eylemime erişmesine izin vermek için böyle bir yöntem süslüyorum

[Authorize(Roles="members")]

Birden fazla role nasıl izin verebilirim? Örneğin aşağıdaki çalışmaz ama ne yapmaya çalışıyorum gösterir ("üye" ve "yönetici" erişimine izin):

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

4
Lütfen bu sorunun kabul edilen cevabını değiştirin. Şu anda kabul edilen cevabı olan kişi, yanlış olduğunu belirterek düzenlemiştir.
Eric

Yanıtlar:


595

Başka bir seçenek, yayınladığınız gibi tek bir yetkilendirme filtresi kullanmak, ancak iç alıntıları kaldırmaktır.

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

5
MVC 5'te de çalışır. +1
gkonuralp

4
ASP.NET Core 1.0 (MVC 6) ve Microsoft.AspNet.Identity v3'te çalışır. *
Soren

3
Yetkilendirmeniz gereken tek bir denetleyiciniz varsa bu sorun olmaz. Birden fazla dosyanız varsa, bu dize sabitlerini (yuck) çoğaltırsınız. Rol adlarına sahip statik sınıfı tercih ederim. Evcil hayvan nefretim yinelenen dizeler ... çok kötü.
robnick

1
@kraeg iyi haber sorununuzu çözdünüz. Şimdi, lütfen yorumlarınızı silmeyi düşünün
Pablo Claus

1
Neden? Bunu çözmek için zamanımı aldı. Aynı sorunu yaşayan bir başkası için yararlı olabilir.
kraeg

129

Özel roller kullanmak istiyorsanız, bunu yapabilirsiniz:

CustomRoles sınıf:

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

kullanım

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

Birkaç rolünüz varsa, belki bunları (netlik için) şu şekilde birleştirebilirsiniz:

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

kullanım

[Authorize(Roles = CustomRoles.AdministratorOrUser)]

7
CustomRoles'un arkasında ne olduğunu bilmeyen insanlara açıklarsanız, bu iyi bir yanıt olacaktır.
James Skemp

1
@ JamesSkemp tamam, cevabımı uzattım. O çok basit. CustumRoles, uygulama sabitlerime karşılık gelen bazı sabitler içeren oluşturduğum bir sınıftır. Bunu birkaç nedenden ötürü yaptım: 1) Yazım hatalarından kaçınmak için akıllıca kullanılmasına izin verir 2) Bakımı kolaylaştırmak için. Bir rol değişikliği varsa, benim uygulama içinde sadece bir yeri güncellemek zorunda.
Pablo Claus

@Pabloker Alternatif olarak Flags özniteliğine sahip bir enum oluşturabilirsiniz, örneğin Convert.ToString (CustomRoles.Administrator | CustomRoles.User); - can sıkıcı kısmı, bunun açık bir dönüşüm gerektirmesidir
cstruter

39 rolünüz varsa?
Kiquenet

Bence probleminiz .net ile yapılabileceklerin ötesinde izinlerin modellenmesinden kaynaklanıyor
Pablo Claus

82

Olası bir basitleştirme, alt sınıfa gitmek olacaktır AuthorizeAttribute:

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

Kullanımı:

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

Anlamsal olarak Jim Schmehil'in cevabı ile aynıdır.


3
Bu benim için işe yaramadı, oturum açmış olan kullanıcı, kullanıcı rollerden birine sahip olmasa bile özniteliği atlayabildi.
Urielzen

9
Bu yanıt, sabitleri değerleriniz olarak kullandığınızda daha iyidir: örneğin [Roller (Constants.Admin, Constants.Owner)]
dalcam

3
Bu en iyi cevap
IgorShch

18

MVC4 için, rollerimle bir Enum( UserRoles) kullanarak , bir özel kullanıyorum AuthorizeAttribute.

Kontrollü eylemimde şunu yaparım:

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

Ve ben AuthorizeAttributeböyle bir özel kullanın :

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

Bu, Fabricio Martínez Tamayo tarafından değiştirilmiş FNHMVC'nin bir parçasıdır https://github.com/fabriciomrtnz/FNHMVC/


1
OnAuthorization yönteminiz kullanıcının tüm numaralandırılmış rollere sahip olmasını gerektirir ; bu kasıtlı mıydı yoksa bu döngüde bir ara mı kaçırıyorsunuz?
Tieson T.

@Tieson: Oldukça yakından inceledim, kesinlikle bu döngüde bir mola gerekli gibi görünüyor.
OcelotXL

@TiesonT. ve @ madrush, düzeltmenizi takdir ediyorum, gerçekten döngü içinde bir mola verebilir. Yukarıdaki kodu değiştireceğim.
Bernardo Loureiro

Enum UserRoles güzel. Manuel olarak mı beyan ediyorsunuz yoksa DB'nin içeriğine göre otomatik olarak mı oluşturuluyor?
Konrad Viltersten

@KonradViltersten Manuel olarak ama sanırım Yansıma ve Dinamik sınıf otomatik olarak oluşturulabilir
Bernardo Loureiro

3

Başka bir açık çözüm, kurallara uymak ve birden çok [Yetkilendir] özelliği eklemek için sabitleri kullanabilirsiniz. Şuna bir bak:

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

Sonra denetleyicide:

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

14
Birden çok Authorizeözellik AND semantics kullanır ve TÜM koşulların yerine getirilmesini gerektirir (yani kullanıcının hem Yönetici hem de Misafir rollerinde olması gerekir).
trousyt

3

Kendinizi bu 2 rolü sık sık uygularsanız, kendi Yetkilendirmelerine göre silebilirsiniz. Bu gerçekten kabul edilen cevabın bir uzantısıdır.

using System.Web.Mvc;

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

Ve sonra yeni yetkinizi Eylem'e uygulayın. Bence bu daha temiz görünüyor ve kolayca okunabiliyor.

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

1

Alt sınıf ekleyerek daha iyi kod 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 }
                  }
              );
            }
        }
    }

Bu nasıl kullanılır

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

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

1

AspNetCore 2.x kullanarak biraz farklı bir yol izlemeniz gerekir:

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

sadece şu şekilde kullanın:

[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
Kod dahil cevaplar, kodun nasıl çalıştığını ve soruyu neden yanıtladığını açıklayan en az bir minimum açıklamaya sahip olmalıdır. Ayrıca kod bölümü biçimlendirmesinin iyileştirilmesi gerekir.
Roberto Caboni

Ha? @Orsit Moel, Yanlış iş parçacığına kopyalanmış gibi görünüyor ...
Cameron Forward
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.