È possibile abilitare [Autorizza] per il controller ma disabilitarlo per una singola azione?

StackOverflow https://stackoverflow.com/questions/329500

  •  11-07-2019
  •  | 
  •  

Domanda

Vorrei usare [Autorizza] per ogni azione nel mio controller di amministrazione tranne l'azione Accedi .

[Authorize (Roles = "Administrator")]
public class AdminController : Controller
{
    // what can I place here to disable authorize?
    public ActionResult Login()
    {
        return View();
    }
}
È stato utile?

Soluzione

Non credo che tu possa farlo con l'attributo Autorizza standard, ma potresti derivare il tuo attributo da AuthorizeAttribute che accetta un elenco di azioni per consentire e consentire l'accesso solo a tali azioni. Puoi consultare la fonte per AuthorizeAttribute su www.codeplex.com per avere idee su come farlo. Se lo facessi, potrebbe apparire come:

[AdminAuthorize (Roles = "Administrator", Exempt = "Login, Logout") ]
public class AdminController : Controller
{
    public ActionResult Login()
    {
        return View();
    }

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

    ... other, restricted actions ...
}

MODIFICA : Cordiali saluti, alla fine mi sono imbattuto nella necessità di fare qualcosa di simile da solo e sono andato in una direzione diversa. Ho creato un provider di filtri di autorizzazione predefinito e ho applicato un filtro di autorizzazione globale. Il provider del filtro di autorizzazione utilizza la riflessione per verificare se un'azione o un controller hanno un attributo di autorizzazione specifico applicato e, in tal caso, lo difende. In caso contrario, applica un filtro di autorizzazione predefinito. Questo è accoppiato con un PublicAttribute derivato da AuthorizeAttribute che consente l'accesso pubblico. Ora ottengo l'accesso protetto predefinito, ma posso concedere l'accesso pubblico tramite [Public] applicato a un'azione o un controller. È inoltre possibile richiedere un'autorizzazione più specifica. Vedi il mio blog su http: // farm-fresh -code.blogspot.com/2011/04/default-authorization-filter-provider.html

Altri suggerimenti

Puoi decorare il tuo controller con [Autorizza] e quindi puoi semplicemente decorare il metodo che vuoi esentare con [AllowAnonymous]

Potresti sovrascrivere il metodo OnAuthorization del controller

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        if ((string)(filterContext.RouteData.Values["action"]) == "Login")
        {
            filterContext.Cancel = true;
            filterContext.Result = Login();
        }
    }

Funziona ma è un hack.

Codice di classe completo utilizzato per i test:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Ajax;

namespace MvcApplication2.Controllers
{
[HandleError]
[Authorize]
public class HomeController : Controller
{
    public ActionResult Index()
    {
        ViewData["Title"] = "Home Page";
        ViewData["Message"] = "Welcome to ASP.NET MVC!";

        return View();
    }


    public ActionResult About()
    {
        ViewData["Title"] = "About Page";

        return View();
    }


    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        if ((string)(filterContext.RouteData.Values["action"]) == "Index")
        {
            filterContext.Cancel = true;
            filterContext.Result = Index();
        }
    }
}
}

Potrebbe non essere reale, ma ho scritto il mio attributo personalizzato:

public class SelectableAuthorizeAttribute : AuthorizeAttribute
{
    public SelectableAuthorizeAttribute(params Type[] typesToExclude)
    {
        _typesToExlude = typesToExclude;
    }

    private readonly Type[] _typesToExlude;

    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        bool skipAuthorization = _typesToExlude.Any(type => filterContext.ActionDescriptor.ControllerDescriptor.ControllerType == type);

        if (!skipAuthorization)
        {
            base.OnAuthorization(filterContext);
        }
    }
}

E poi registrato nei miei filtri globali:

filters.Add(new SelectableAuthorizeAttribute(typeof(MyController)));

Spero che sia utile per qualcuno

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top