Ist es möglich, alle Handler für eine Richtlinie inline anstatt mit einem Attribut auszuführen?

8

Bei den meisten meiner APIs mache ich einfach eine Autorisierung wie folgt:

[Authorize(Policy = "Foo")]
public MyApi()

Ich erhalte diese Richtlinie jedoch von einem NuGet und kann sie nicht ändern.

Für einige meiner APIs möchte ich diese Richtlinie nicht immer haben. Dies muss zur Laufzeit anhand einer Konfiguration herausgefunden werden. Ich möchte eine Möglichkeit haben, dies inline auszuführen und sicherzustellen, dass alle Handler, die eingerichtet werden, ausgeführt werden.

Nach langem Suchen habe ich festgestellt, dass ich eine erstelle IAuthorizationServiceund diese zum Aufrufen verwende AuthorizeAsync. Dies scheint das zu sein, was ich will, aber das Problem, auf das ich jetzt stoße, ist, dass sich alle Handler auf a AuthorizationFilterContextals Ressource für den Kontext verlassen. Dies scheint automatisch zu geschehen, wenn die Autorisierung über das Attribut erfolgt, jedoch nicht über den Aufruf von AuthorizeAsync. In diesem Fall muss es manuell übergeben werden. Mein Code sieht jetzt so aus:

public MyApi()
{
    var allowed = await _authorizationService.AuthorizeAsync(User, null, "Foo").ConfigureAwait(false);
}

Dies scheint alle meine Handler korrekt zu durchlaufen, aber sie funktionieren nicht, weil die fehlen AuthorizationFilterContext.

1) Ist dies zunächst der richtige Ansatz oder gibt es eine andere Möglichkeit, dies inline zu tun? Ich vermute, es gibt wahrscheinlich eine Möglichkeit, meine eigene Richtlinie zu erstellen, die diese umschließt, und ich kann die Konfiguration dort überprüfen, aber wenn es einen einfachen Inline-Ansatz gibt, würde ich das vorziehen.

2) Wenn dieser Weg gültig ist, gibt es einen guten Weg, um das zu bekommen AuthorizationFilterContext? Ich habe versucht, es manuell zu erstellen, aber ich befürchte, dass dies nicht korrekt ist, ohne mehr Daten aus dem Kontext zu übergeben, aber ich kann keine guten Beispiele / Dokumente finden:

new AuthorizationFilterContext(new ActionContext(HttpContext, HttpContext.GetRouteData(), new ActionDescriptor()), new IFilterMetadata[] { });

user3715648
quelle
Dies ist ein wirklich schlechter Weg, dies zu tun. Erstens kann jeder Aufruf jetzt Ihre API-Methode treffen, obwohl sie keinen Zugriff darauf haben, da Sie die Zugriffsprüfung zu einem späteren Zeitpunkt durchführen. Erstellen Sie ein benutzerdefiniertes Attribut für sich selbst, und Sie können ganz einfach überprüfen, ob die zu überprüfende Richtlinie (entweder einzeln oder mehrfach) dem Benutzer gehört oder nicht. Lesen Sie auch Folgendes
neugierigBoy

Antworten:

-2

Es wird keine geben, AuthorizationFilterContextwenn Sie sich außerhalb der Autorisierungspipeline befinden. Sie sollten daher die Authentifizierung nicht inline mit behandeln IAuthorizationService.

Dies scheint alle meine Handler korrekt zu durchlaufen, aber sie funktionieren nicht, weil die fehlen AuthorizationFilterContext.

Klingt so, als hätten Sie die Kontrolle über die Authentifizierungshandler. Haben Sie versucht, die Kurzschlussauthentifizierung im Handler durchzuführen, wenn dies nicht erforderlich ist?

Der Handler kann Dienste über den DI abrufen, sodass Sie Ihre erforderliche Laufzeitkonfiguration über IOptions oder IHttpContextAccessor und was auch immer eingeben können .

Sebastian
quelle
-2

Können Sie kein eigenes AuthorizeAttribut erstellen , das das aktuelle erbt und die Richtlinie intern auflöst? Oder noch besser versuchenIAuthorizationPolicyProvider

class MyPolicyProvider : IAuthorizationPolicyProvider
{
    private DefaultAuthorizationPolicyProvider BackupPolicyProvider { get; }

    public MyPolicyProvider()
    {
        BackupPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
    }

    public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
    {
        if (policyName.Equals("Foo"))
        {
            bool myConditionToAvoidPolicy = true;
            if (myConditionToAvoidPolicy)
            {
                return Task.FromResult<AuthorizationPolicy>(null);
            }
        }

        return BackupPolicyProvider.GetPolicyAsync(policyName);
    }
}

Dies ist nicht getestet, aber Sie können hier mehr darüber finden .

zhuber
quelle
-2

Ihre Überprüfungsbedingung scheint zu einem späteren Zeitpunkt zu geschehen, was ich nicht für eine gute Idee halte. Ihre API-Methode ist anfällig und immer noch offen, da Ihre Überprüfung zu einem späteren Zeitpunkt durchgeführt wird. Mit dem Attribut können Sie es jedoch auf einer früheren Ebene erfassen und dennoch die benutzerdefinierte Logik anwenden. Am Ende des Tages entscheidet alles, was es entscheidet, entweder "Ja, Zugang haben" oder "Nein, kein Zugang für Sie !!" Das Folgende ist nicht getestet, sollte Sie aber zum Laufen bringen:

public class CustomAuthorize : AuthorizeAttribute
{
    private readonly PermissionAction[] permissionActions;

    public CustomAuthorize(PermissionItem item, params PermissionAction[] permissionActions)
    {
        this.permissionActions = permissionActions;
    }

    public override void OnAuthorization(HttpActionContext actionContext)
    {
        var currentIdentity = System.Threading.Thread.CurrentPrincipal.Identity;
        if (!currentIdentity.IsAuthenticated) {
            // no access
        }

        bool myCondition = "money" == "happiness"; 
        if(myCondition){
           // do your magic here...
        }
        else{
          // another magic...
       }           
    }
}
neugierigBoy
quelle