Odczytywanie tekstu autoryzacji w Netcore API 3.1

9

Mam działający projekt Netcore 2.2, w którym zaimplementowałem niestandardowe zasady sprawdzające klucze API.

W startup.cs dodaję tę zasadę w ten sposób

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

W moim AppKeyRequirement dziedziczę po AuthorizationHandler i rozwiązuję klucze w przychodzących żądaniach w ten sposób

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

To nie działa w Netcore 3.1

Otrzymuję następujący błąd:

Nie można rzutować obiektu typu „Microsoft.AspNetCore.Routing.RouteEndpoint”, aby wpisać „Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext”.

Jak to zrobić w rdzeniu 3 i nowszych?

Jak zauważył Kirk Larkin, poprawnym sposobem w .net 3.0 i nowszych jest wstrzyknięcie IHttpContextAccessor do modułu obsługi autoryzacji i użycie go.

Moje pytanie w tym momencie brzmi: jak to wstrzyknąć? Nie mogę przekazać tego w startup.cs lub przynajmniej nie widzę jak.

Wszelkie pomysły / wskazówki będą mile widziane.

w2olves
źródło

Odpowiedzi:

14

W wersjach wcześniejszych niż ASP.NET Core 3.0 implementacje IAuthorizationHandlerzostały wywołane podczas potoku MVC. W wersji 3.0, która korzysta z routingu punktów końcowych (domyślnie), te implementacje są wywoływane przez oprogramowanie pośredniczące autoryzacji ( UseAuthorization()). To oprogramowanie pośrednie działa przed potokiem MVC, a nie jako jego część.

Ta zmiana oznacza, że AuthorizationFilterContextnie jest już przekazywana osobom zajmującym się obsługą autoryzacji. Zamiast tego jest to instancja RouteEndpoint, która nie zapewnia dostępu do HttpContext.

W twoim przykładzie używasz tylko AuthorizationFilterContextdo zdobycia HttpContext. W wersji 3.0+ wstrzyknij IHttpContextAccessorprogram obsługi autoryzacji i użyj go. Oto przykład kompletności:

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"))
        {
            // ...
        }
    }
}

Konieczne może być również zarejestrowanie się IHttpContextAccessorw ConfigureServices:

services.AddHttpContextAccessor();

Zobacz Użyj HttpContext z niestandardowych składników, aby uzyskać więcej informacji na temat używania IHttpContextAccessor.

Kirk Larkin
źródło
1
Dziękuję za tę wskazówkę. Usiłuję utworzyć zasadę, w której jeśli brakuje klucza API, połączenie zostanie odrzucone. Czy nie możemy już korzystać z // Dodaj kluczowych zasad Policy.AddAuthorization (options => {options.AddPolicy („AppKey”, policy => policy.Requirements.Add (new AppKeyRequirement ()));}); Jeśli nie, jak mogę przechwycić połączenie, zanim uderzy ono w działanie kontrolera?
w2olves
1
Tak, to nadal działa tak samo jak poprzednio.
Kirk Larkin
Konstruktor oczekuje IHttpContextAccessor, w jaki sposób mogę przekazać to podczas tworzenia zasad w pliku Startup.cs? services.AddAuthorization (options => {options.AddPolicy („AppKey”, policy => policy.Requirements.Add (new AppKeyRequirement ()));}); Mogę również utworzyć nowy domyślny konstruktor dla AppKeyAuthorizationHandler, ale następnie httpContextAccessor.HttpContext; jest zerowy, gdy nadejdzie żądanie. Wszelkie pomysły?
w2olves
1
Dodajesz swój moduł obsługi za pomocą DI, który tworzy dla ciebie jego instancję i przekazuje w IHttpContextAccessor. Zobacz dokumenty .
Kirk Larkin