È possibile abilitare [Autorizza] per il controller ma disabilitarlo per una singola azione?
-
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();
}
}
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