Wenn ich das Authorize-Attribut sowohl auf dem Controller als auch auf der Aktion habe, welches wird den Effekt haben? Oder werden beide wirksam?
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:
Wenn ich das Authorize-Attribut sowohl für den Controller als auch für die Aktion habe, welches wird den Effekt haben? Beide?
Um dies einfach zu beantworten: Beides. Der Effekt ist auf AND
die beiden Einschränkungen zusammen. Ich werde unten erklären, warum ...
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 Zugriff AllUsersIndex
müssen Sie sich daher in der Rolle "Benutzer" befinden. Für den Zugriff AdminUsersIndex
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 die Users
Eigenschaft des Attributs, die kombiniert werden kann Roles
, 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 .
[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.
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 durch DefaultAuthorize
den if (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();
}
}
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 die AuthorizeAttribute.OnAuthorization
Basismethode nicht aufrufen müssen , um zur normalen Autorisierung zu gelangen. Dies bedeutet, dass selbst wenn Sie die Basismethode nicht explizit aufrufen, die Basis AuthorizeAttribute
die Autorisierung kurzschließen kann, indem der Zugriff verboten wird.
Was ich getan habe ist, dass ich eine erstellt habe DefaultAuthorizeAttribute
, die nicht von AuthorizeAttribute
, sondern von erbt Attribute
. Da das DefaultAuthorizeAttribute
nicht erbt von AuthorizeAttribute
, 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) { }
}
OnAuthorizationAsync
- es wird GetEffectivePolicyAsync
immer null zurückgegeben, da dies GetEffectivePolicyAsync
nur mit Filtern funktioniert, die tatsächlich auf den Controller / die Aktion angewendet werden, was unser Autorisierungsfilter nicht ist. Wir behalten es nur in m_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...
[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 zwei Authorize
Attribute (eines auf dem Controller, eines auf der Aktion), nicht Authorize
dann AllowAnonymous
. Ich habe eine weitere Antwort hinzugefügt, um meinen Standpunkt zu veranschaulichen.