Lesen des AuthorizationFilterContext in der Netcore-API 3.1

9

Ich habe ein funktionierendes Netcore 2.2-Projekt, in dem ich eine benutzerdefinierte Richtlinie implementiert habe, die nach API-Schlüsseln sucht.

In der Datei startup.cs füge ich diese Richtlinie folgendermaßen hinzu

//Add Key Policy
services.AddAuthorization(options =>
{
    options.AddPolicy("AppKey", policy => policy.Requirements.Add(new AppKeyRequirement()));
});

In meiner AppKeyRequirement erbe ich von AuthorizationHandler und löse die Schlüssel in den eingehenden Anforderungen wie folgt auf

protected override Task HandleRequirementAsync(AuthorizationHandlerContext authContext, AppKeyRequirement requirement)
{
    var authorizationFilterContext = (AuthorizationFilterContext)authContext.Resource;
    var query = authorizationFilterContext.HttpContext.Request.Query;

    if (query.ContainsKey("key") && query.ContainsKey("app"))
    { // Do stuff

Dies funktioniert in Netcore 3.1 nicht

Ich erhalte die folgende Fehlermeldung:

Objekt vom Typ 'Microsoft.AspNetCore.Routing.RouteEndpoint' kann nicht in Typ 'Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext' umgewandelt werden.

Was ist der richtige Weg, um dies in Kern 3 und höher zu tun?

Wie von Kirk Larkin hervorgehoben, besteht der richtige Weg in .net 3.0 und höher darin, IHttpContextAccessor in den Auth-Handler zu injizieren und diesen zu verwenden.

Meine Frage an dieser Stelle ist, wie ich das injiziere. Ich kann dies nicht in startup.cs übergeben oder zumindest sehe ich nicht wie.

Alle Ideen / Hinweise werden sehr geschätzt.

w2olves
quelle

Antworten:

14

In Versionen vor ASP.NET Core 3.0 wurden Implementierungen von IAuthorizationHandlerwährend der MVC-Pipeline aufgerufen. Ab Version 3.0, die (standardmäßig) Endpoint-Routing verwendet, werden diese Implementierungen von der Autorisierungs-Middleware ( UseAuthorization()) aufgerufen . Diese Middleware läuft vorher der MVC-Pipeline ausgeführt und nicht als Teil davon.

Diese Änderung bedeutet, dass sie AuthorizationFilterContextnicht mehr an Berechtigungshandler übergeben wird. Stattdessen ist es eine Instanz von RouteEndpoint, die keinen Zugriff auf die bietet HttpContext.

In Ihrem Beispiel verwenden Sie nur, um AuthorizationFilterContextzu erreichen HttpContext. In 3.0+ injizieren Sie IHttpContextAccessorin Ihren Autorisierungshandler und verwenden Sie diesen. Hier ist ein Beispiel für die Vollständigkeit:

public class AppKeyAuthorizationHandler : AuthorizationHandler<AppKeyRequirement>
{
    private readonly IHttpContextAccessor httpContextAccessor;

    public AppKeyAuthorizationHandler(IHttpContextAccessor httpContextAccessor)
    {
        this.httpContextAccessor = httpContextAccessor;
    }

    protected override Task HandleRequirementAsync(
        AuthorizationHandlerContext authContext, AppKeyRequirement requirement)
    {
        var httpContext = httpContextAccessor.HttpContext;
        var query = httpContext.Request.Query;

        if (query.ContainsKey("key") && query.ContainsKey("app"))
        {
            // ...
        }
    }
}

Möglicherweise müssen Sie sich auch registrieren IHttpContextAccessorin ConfigureServices:

services.AddHttpContextAccessor();

Weitere Informationen zur Verwendung finden Sie unter Verwenden von HttpContext aus benutzerdefinierten KomponentenIHttpContextAccessor .

Kirk Larkin
quelle
1
Vielen Dank für diesen Hinweis. Ich versuche, eine Richtlinie zu erstellen, bei der der Aufruf abgelehnt wird, wenn ein API-Schlüssel fehlt. Können wir // Key Policy Services nicht mehr verwenden.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (new AppKeyRequirement ()));}); Wenn nicht, wie kann ich einen Anruf abfangen, bevor er eine Controller-Aktion ausführt?
w2olves
1
Ja, das funktioniert immer noch genauso wie zuvor.
Kirk Larkin
Der Konstruktor erwartet IHttpContextAccessor. Wie kann ich dies übergeben, wenn ich die Richtlinie in Startup.cs erstelle? services.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (neues AppKeyRequirement ()));}); Ich kann auch einen neuen Standardkonstruktor für AppKeyAuthorizationHandler erstellen, dann aber httpContextAccessor.HttpContext; ist null, wenn eine Anfrage eingeht. Irgendwelche Ideen?
w2olves
1
Sie fügen Ihren Handler mit DI hinzu, wodurch eine Instanz davon für Sie erstellt und die übergeben wird IHttpContextAccessor. Siehe die Dokumente .
Kirk Larkin