Asp.net MVC4: autorizza sia il controller che l’azione

Se ho l’attributo Authorize sia sul controller che sull’azione, quale avrà l’effetto? O entrambi avranno effetto?

    Hai chiesto:

    Se ho attributo Authorize sia sul controller che sull’azione, quale avrà l’effetto? Entrambi?

    Per rispondere semplicemente: entrambi. L’effetto è su AND le due restrizioni insieme. Spiegherò perché sotto …

    Dettagli

    Quindi, ci sono alcuni motivi per cui potresti chiedertelo.

    1. Vuoi sapere come applicare un vincolo aggiuntivo su un’azione rispetto a un metodo. per esempio
      • A livello di controller, impone agli utenti il ​​ruolo “utente”
      • A livello di azione, impone inoltre agli utenti il ​​ruolo di “admin”
    2. Si desidera sostituire il vincolo del controller al livello di azione
    3. Si desidera rimuovere il vincolo del controller a livello di azione e rendere il metodo disponibile agli utenti anonimi

    Non hai specificato la tua versione MVC, quindi assumerò l’ultima versione di oggi (MVC 4.5). Tuttavia, ciò non cambierà molto la risposta anche se si stesse utilizzando MVC 3.

    [Anonymous] sostituisce il controller [Authorize] (caso 3)

    Caso 3. Non ho bisogno di coprire (l’uso di [AllowAnonymous] ) come è stato già risposto in tutto SO e su tutto il web . Basti dire che se si specifica [AllowAnonymous] su un’azione, questa verrà resa pubblica anche se il controller ha [Authorize] .

    È inoltre ansible sottoporre un intero sito Web all’authorization utilizzando un filtro globale e utilizzare AllowAnonymous sulle poche azioni o controller che si desidera rendere pubblici.

    [Authorize] è additivo (caso 1)

    Il caso 1 è facile. Prendi il seguente controller come esempio:

     [Authorize(Roles="user")] public class HomeController : Controller { public ActionResult AllUsersIndex() { return View(); } [Authorize(Roles = "admin")] public ActionResult AdminUsersIndex() { return View(); } } 

    Per impostazione predefinita [Authorize(Roles="user")] rende tutte le azioni nel controller disponibili solo per gli account nel ruolo “utente”. Pertanto per accedere a AllUsersIndex devi essere nel ruolo “utente”. Tuttavia per accedere a AdminUsersIndex devi essere sia nel ruolo “utente” che nel ruolo “admin”. Per esempio:

    • UserName: Bob, Ruoli: utente, imansible accedere a AdminUsersIndex , ma può accedere a AllUsersIndex
    • UserName: Jane, Ruoli: admin, imansible accedere a AdminUsersIndex o AllUsersIndex
    • UserName: Tim, Ruoli: utente e amministratore, possono accedere a AdminUsersIndex e AllUsersIndex

    Questo dimostra che l’attributo [Authorize] è additivo. Questo vale anche per la proprietà Users dell’attributo, che può essere combinata con i Roles per renderlo ancora più restrittivo.

    Questo comportamento è dovuto al modo in cui funzionano gli attributi di controller e azione. Gli attributi sono concatenati tra loro e applicati nel controller dell’ordine e quindi nell’azione. Se il primo rifiuta l’authorization, controlla i ritorni e l’attributo dell’azione non viene chiamato. Se il primo passa l’authorization, viene controllato anche il secondo. È ansible sovrascrivere questo ordine specificando Order (ad esempio [Authorize(Roles = "user", Order = 2)] ).

    Sovrascrittura [Authorize] (caso 2)

    Il caso 2 è più complicato. Ricordiamo dall’alto che gli attributi [Authorize] sono esaminati nell’ordine (Globale quindi) Controller quindi Azione. Il primo a rilevare che l’utente non è idoneo per essere autorizzato vince, gli altri non vengono chiamati.

    Un modo per aggirare questo è definire due nuovi attributi come di seguito. [OverrideAuthorize] non fa altro che differire a [Authorize] ; il suo unico scopo è definire un tipo che possiamo verificare. [DefaultAuthorize] ci consente di verificare se l’Azione chiamata nella richiesta è decorata con [OverrideAuthorize] . Se lo è, rimandiamo al controllo di authorization Azione, altrimenti procediamo con il controllo del livello del controller.

     public class DefaultAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { var action = filterContext.ActionDescriptor; if (action.IsDefined(typeof(OverrideAuthorizeAttribute), true)) return; base.OnAuthorization(filterContext); } } public class OverrideAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); } } 

    Possiamo quindi usarlo in questo modo:

     [DefaultAuthorize(Roles="user")] public class HomeController : Controller { // Available to accounts in the "user" role public ActionResult AllUsersIndex() { return View(); } // Available only to accounts both in the "user" and "admin" role [Authorize(Roles = "admin")] public ActionResult AdminUsersIndex() { return View(); } // Available to accounts in the "superuser" role even if not in "user" role [OverrideAuthorize(Roles = "superuser")] public ActionResult SuperusersIndex() { return View(); } } 

    Nell’esempio sopra, SuperusersIndex è disponibile per un account con il ruolo di “superutente”, anche se non ha il ruolo “utente”.

    Vorrei aggiungere qualcosa a Overriding [Authorize] (caso 2)

    OverrideAuthorizeAttribute e DefaultAuthorizeAttribute funzionano bene, ma scopro che puoi anche utilizzare OverrideAuthorizationAttribute che sostituisce i filtri di authorization definiti a un livello superiore.

     [Authorize(Roles="user")] public class HomeController : Controller { // Available to accounts in the "user" role public ActionResult AllUsersIndex() { return View(); } // Available only to accounts both in the "user" and "admin" role [Authorize(Roles = "admin")] public ActionResult AdminUsersIndex() { return View(); } // Available to accounts in the "superuser" role even if not in "user" role [OverrideAuthorization()] [Authorize(Roles = "superuser")] public ActionResult SuperusersIndex() { return View(); } } 

    Se lo si utilizza sul controller, verranno eseguiti tutti i metodi di questo controller.

     [Authorize] public class SomeController(){ // all actions are effected public ActionResult Action1 public ActionResult Action2 

    Se vuoi impedire una di queste azioni, puoi usare qualcosa del genere:

     [Authorize] public class SomeController(){ // all actions are effected public ActionResult Action1 public ActionResult Action2 [AllowAnonymous] public ActionResult Action3 // only this method is not effected...