Wenn ich das Authorize-Attribut sowohl auf dem Controller als auch auf der Aktion habe, welches wird den Effekt haben? Oder werden beide wirksam?
73
Wenn ich das Authorize-Attribut sowohl auf dem Controller als auch auf der Aktion habe, welches wird den Effekt haben? Oder werden beide wirksam?
Antworten:
Du hast gefragt:
Um dies einfach zu beantworten: Beides. Der Effekt ist auf
AND
die beiden Einschränkungen zusammen. Ich werde unten erklären, warum ...Einzelheiten
Es gibt also einige Gründe, warum Sie dies fragen könnten.
Sie haben Ihre MVC-Version nicht angegeben, daher gehe ich von der neuesten Version (MVC 4.5) aus. Dies ändert jedoch nichts an der Antwort, selbst wenn Sie MVC 3 verwenden.
[Anonymous]
überschreibt den Controller[Authorize]
(Fall 3)Fall 3. Ich muss mich nicht mit (der Verwendung von
[AllowAnonymous]
) befassen, da dies bereits in SO und im gesamten Web beantwortet wurde . Es genügt zu sagen: Wenn Sie[AllowAnonymous]
eine Aktion angeben , wird diese Aktion auch dann öffentlich, wenn der Controller[Authorize]
sie aktiviert hat .Sie können auch eine gesamte Website mithilfe eines globalen Filters autorisieren und
AllowAnonymous
für die wenigen Aktionen oder Controller verwenden, die Sie veröffentlichen möchten.[Authorize]
ist additiv (Fall 1)Fall 1 ist einfach. Nehmen Sie als Beispiel den folgenden Controller:
[Authorize(Roles="user")] public class HomeController : Controller { public ActionResult AllUsersIndex() { return View(); } [Authorize(Roles = "admin")] public ActionResult AdminUsersIndex() { return View(); } }
Standardmäßig sind
[Authorize(Roles="user")]
alle Aktionen im Controller nur für Konten in der Rolle "Benutzer" verfügbar. Für den ZugriffAllUsersIndex
müssen Sie sich daher in der Rolle "Benutzer" befinden. Für den ZugriffAdminUsersIndex
müssen Sie sich jedoch sowohl in der Rolle "Benutzer" als auch in der Rolle "Administrator" befinden. Zum Beispiel:AdminUsersIndex
, kann aber zugreifenAllUsersIndex
AdminUsersIndex
oder zugreifenAllUsersIndex
AdminUsersIndex
und zugreifenAllUsersIndex
Dies zeigt, dass das
[Authorize]
Attribut additiv ist. Dies gilt auch für dieUsers
Eigenschaft des Attributs, die kombiniert werden kannRoles
, um es noch restriktiver zu machen.Dieses Verhalten ist auf die Funktionsweise der Controller- und Aktionsattribute zurückzuführen. Die Attribute werden miteinander verkettet und in der Auftragssteuerung dann Aktion angewendet. Wenn der erste die Autorisierung verweigert, wird die Steuerung zurückgegeben und das Attribut der Aktion wird nicht aufgerufen. Wenn der erste die Autorisierung besteht, wird auch der zweite geprüft. Sie können diese Reihenfolge überschreiben, indem Sie
Order
(zum Beispiel[Authorize(Roles = "user", Order = 2)]
) angeben .Überschreiben
[Authorize]
(Fall 2)Fall 2 ist schwieriger. Erinnern Sie sich von oben daran, dass die
[Authorize]
Attribute in der Reihenfolge (Global dann) Controller und dann Aktion untersucht werden. Der erste, der feststellt, dass der Benutzer nicht zur Autorisierung berechtigt ist, gewinnt, die anderen werden nicht angerufen.Eine Möglichkeit, dies zu umgehen, besteht darin, zwei neue Attribute wie folgt zu definieren. Das
[OverrideAuthorize]
tut nichts anderes als aufzuschieben[Authorize]
; Der einzige Zweck besteht darin, einen Typ zu definieren, nach dem wir suchen können. Damit[DefaultAuthorize]
können wir überprüfen, ob die in der Anfrage aufgerufene Aktion mit einem gekennzeichnet ist[OverrideAuthorize]
. Wenn dies der Fall ist, verschieben wir die Überprüfung der Aktionsautorisierung, andernfalls fahren wir mit der Überprüfung der Controller-Ebene fort.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); } }
Wir können es dann so verwenden:
[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(); } }
Im obigen Beispiel
SuperusersIndex
steht ein Konto mit der Rolle "Superuser" zur Verfügung, auch wenn es nicht die Rolle "Benutzer" hat.quelle
if(condition1&&condition2)
wenn die erste Bedingung falsch ist, der Compailer nicht nach der zweiten Bedingung sucht und den if-Block überspringt.SuperusersIndex
Aktionsmethode?OverrideAuthorize
ersetzt vollständig die Standardberechtigungen, die durchDefaultAuthorize
denif (action.IsDefined(typeof(OverrideAuthorizeAttribute), true)) return;
inDefaultAuthorizeAttribute.OnAuthorization
[OverrideAuthorization]
Attributs zur Aktion ausgeführt werden, wie in dieser Antwort beschrieben .Ich möchte Overriding [Authorize] etwas hinzufügen (Fall 2)
OverrideAuthorizeAttribute und DefaultAuthorizeAttribute funktionieren einwandfrei, aber ich stelle fest, dass Sie auch OverrideAuthorizationAttribute verwenden können, das auf einer höheren Ebene definierte Berechtigungsfilter überschreibt.
[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(); } }
quelle
Ich habe den zweiten Fall dieser Antwort für ASP.NET Core 2.1 angepasst.
Der Unterschied zu ASP.NET Core
AuthorizeAttribute
besteht darin, dass Sie dieAuthorizeAttribute.OnAuthorization
Basismethode nicht aufrufen müssen , um zur normalen Autorisierung zu gelangen. Dies bedeutet, dass selbst wenn Sie die Basismethode nicht explizit aufrufen, die BasisAuthorizeAttribute
die Autorisierung kurzschließen kann, indem der Zugriff verboten wird.Was ich getan habe ist, dass ich eine erstellt habe
DefaultAuthorizeAttribute
, die nicht vonAuthorizeAttribute
, sondern von erbtAttribute
. Da dasDefaultAuthorizeAttribute
nicht erbt vonAuthorizeAttribute
, musste ich das Autorisierungsverhalten neu erstellen.[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)] public class DefaultAuthorizeAttribute : Attribute, IAuthorizationFilter { private readonly AuthorizeFilter m_authorizeFilter; public DefaultAuthorizeAttribute(params string[] authenticationSchemes) { var policyBuilder = new AuthorizationPolicyBuilder() .AddAuthenticationSchemes(authenticationSchemes) .RequireAuthenticatedUser(); m_authorizeFilter = new AuthorizeFilter(policyBuilder.Build()); } public void OnAuthorization(AuthorizationFilterContext filterContext) { if (filterContext.ActionDescriptor is ControllerActionDescriptor controllerAction && controllerAction.MethodInfo.GetCustomAttributes(typeof(OverrideAuthorizeAttribute), true).Any()) { return; } m_authorizeFilter.OnAuthorizationAsync(filterContext).Wait(); } } public class OverrideAuthorizeAttribute : AuthorizeAttribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationFilterContext filterContext) { } }
quelle
OnAuthorizationAsync
- es wirdGetEffectivePolicyAsync
immer null zurückgegeben, da diesGetEffectivePolicyAsync
nur mit Filtern funktioniert, die tatsächlich auf den Controller / die Aktion angewendet werden, was unser Autorisierungsfilter nicht ist. Wir behalten es nur inm_authorizeFilter
...Wenn Sie es dann auf dem Controller verwenden, werden alle Methoden dieses Controllers ausgeführt.
[Authorize] public class SomeController(){ // all actions are effected public ActionResult Action1 public ActionResult Action2
Wenn Sie eine dieser Aktionen verhindern möchten, können Sie Folgendes verwenden:
[Authorize] public class SomeController(){ // all actions are effected public ActionResult Action1 public ActionResult Action2 [AllowAnonymous] public ActionResult Action3 // only this method is not effected...
quelle
[Authorize]
sowohl den Controller als auch die Aktion " Welches wird den Effekt haben? Beide? " Anlegen. Sie haben darauf nicht geantwortet.Authorize
Attribute Kette zusammen. Wenn der erste den Benutzer zulässt, kann der zweite den Benutzer weiterhin blockieren. Die Frage betrifft auch zweiAuthorize
Attribute (eines auf dem Controller, eines auf der Aktion), nichtAuthorize
dannAllowAnonymous
. Ich habe eine weitere Antwort hinzugefügt, um meinen Standpunkt zu veranschaulichen.