Autorisierungsattribut in ASP.NET MVC überschreiben

83

Ich habe eine MVC-Controller-Basisklasse, auf die ich das Authorize-Attribut angewendet habe, da fast alle Controller (und ihre Aktionen) autorisiert werden sollen.

Ich muss jedoch einen Controller und eine Aktion eines anderen Controllers nicht autorisiert haben. Ich wollte sie mit dem dekorieren können[Authorize(false)] oder so , aber das ist nicht verfügbar.

Irgendwelche Ideen?

Andrei Rînea
quelle

Antworten:

100

Bearbeiten: Seit ASP.NET MVC 4 besteht der beste Ansatz darin, einfach das integrierte AllowAnonymous- Attribut zu verwenden.

Die folgende Antwort bezieht sich auf frühere Versionen von ASP.NET MVC

Sie können ein benutzerdefiniertes Autorisierungsattribut erstellen, das vom Standard-AuthorizeAttribute mit einem optionalen bool-Parameter erbt, um anzugeben, ob eine Autorisierung erforderlich ist oder nicht.

public class OptionalAuthorizeAttribute : AuthorizeAttribute
{
    private readonly bool _authorize;

    public OptionalAuthorizeAttribute()
    {
        _authorize = true;
    }

    public OptionalAuthorizeAttribute(bool authorize)
    {
        _authorize = authorize;
    }

    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        if(!_authorize)
            return true;

                    return base.AuthorizeCore(httpContext);
    }
}

Dann können Sie Ihren Basis-Controller mit folgendem Attribut dekorieren:

[OptionalAuthorize]
public class ControllerBase : Controller
{
}

und für alle Controller, für die Sie keine Autorisierung wünschen, verwenden Sie einfach die Überschreibung mit einem 'false' - z

[OptionalAuthorize(false)]
public class TestController : ControllerBase
{
    public ActionResult Index()
    {
        return View();
    }
}
Steve Willcock
quelle
Ich habe darüber nachgedacht, aber ich hatte auf eine einfachere Lösung gehofft. Wenn "sie" jedoch keine bereitgestellt haben, ist Ihre Lösung die beste.
Andrei Rînea
2
Es ist besser, ein [AllowAnonymous]Attribut zu verwenden .
Jaider
Warten Sie ... damit der Controller nur das Attribut der obersten Klasse eines bestimmten Typs berücksichtigt?
Triynko
Wissen Sie, warum es eigentlich BESSER ist, AllowAnonymous zu verwenden? Weil Sie eine feinere Kontrolle haben. In meinem Fall möchte ich Autorisierungsendpunkte nur für bestimmte Umgebungen deaktivieren. Sie benötigen sie beispielsweise nicht für localhost. Dies bietet eine elegantere Lösung als das, was ich in meinem Startup.cs tun wollte. Wir sprechen hier 11 Jahre später.
Sksallaj
76

Es scheint, dass ASP.NET MVC 4 dies durch Hinzufügen eines AllowAnonymous- Attributs 'behoben' hat .

David Hayden schrieb darüber :

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    public ActionResult Login()
    {
        // ...
    }

    // ...
}
Andrei Rînea
quelle
15

Meine persönliche Einstellung dazu wäre, den Controller aufzuteilen. Erstellen Sie einfach einen anderen Controller. Für die Aktionen benötigen Sie keine Authentifizierung.

Oder Sie könnten haben:

  • BaseController
    erfordert keine Authentifizierung - hier hast du all deine "Basissachen" :).

  • BaseAuthController : BaseController
    Alle Aktionen hier erfordern eine Authentifizierung.

Auf diese Weise können Sie sich authentifizieren, wenn Sie möchten, indem Sie einfach von einer bestimmten Klasse ableiten.

Sirrocco
quelle
6

Wenn Sie nur möchten, dass eine Aktion auf einem ansonsten autorisierten Controller nicht autorisiert wird, können Sie Folgendes tun:

public class RequiresAuthorizationAttribute : ActionFilterAttribute
{
    private readonly bool _authorize;

    public RequiresAuthorizationAttribute()
    {
        _authorize = true;
    }

    public RequiresAuthorizationAttribute(bool authorize)
    {
        _authorize = authorize;
    }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var overridingAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof (RequiresAuthorizationAttribute), false);

        if (overridingAttributes.Length > 0 && overridingAttributes[0] as RequiresAuthorizationAttribute != null && !((RequiresAuthorizationAttribute)overridingAttributes[0])._authorize)
            return;

        if (_authorize)
        {
            //redirect if not authenticated
            if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
            {
                //use the current url for the redirect
                var redirectOnSuccess = filterContext.HttpContext.Request.Url.AbsolutePath;

                //send them off to the login page
                //var redirectUrl = string.Format("?RedirectUrl={0}", redirectOnSuccess);
                var loginUrl = LinkBuilder.BuildUrlFromExpression<HomeController>(filterContext.RequestContext, RouteTable.Routes,
                                                                                  x => x.Login(redirectOnSuccess));
                filterContext.HttpContext.Response.Redirect(loginUrl, true);
            }
        }
    }
}
pondermatisch
quelle