Чтение AuthorizationFilterContext в Netcore API 3.1

9

У меня есть работающий проект netcore 2.2, в котором я реализовал собственную политику, которая проверяет наличие ключей API.

В startup.cs я добавляю эту политику, как это

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

В моем AppKeyRequirement я наследую от AuthorizationHandler и разрешаю ключи во входящих запросах, как это

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

Это не работает в Netcore 3.1

Я получаю следующую ошибку:

Невозможно привести объект типа «Microsoft.AspNetCore.Routing.RouteEndpoint» к типу «Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext».

Как правильно сделать это в ядре 3 и выше?

Как указал Кирк Ларкин, правильный путь в .net 3.0 и выше - внедрить IHttpContextAccessor в обработчик Auth и использовать его.

Мой вопрос на данный момент: как мне это ввести? Я не могу передать это в startup.cs или, по крайней мере, я не вижу, как.

Любые идеи / советы будут высоко ценится.

w2olves
источник

Ответы:

14

В версиях, предшествующих ASP.NET Core 3.0, реализации IAuthorizationHandlerвызывались во время конвейера MVC. Начиная с версии 3.0, которая использует маршрутизацию конечных точек (по умолчанию), эти реализации вызываются промежуточным ПО авторизации ( UseAuthorization()). Это промежуточное программное обеспечение работает до конвейера MVC, а не как его часть.

Это изменение означает, что AuthorizationFilterContextбольше не передается обработчикам авторизации. Вместо этого это экземпляр RouteEndpoint, который не предоставляет доступ к HttpContext.

В вашем примере вы используете только, AuthorizationFilterContextчтобы заполучить HttpContext. В версии 3.0+ внедрите IHttpContextAccessorв свой обработчик авторизации и используйте его. Вот пример для полноты:

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

Вам также может понадобиться зарегистрироваться IHttpContextAccessorв ConfigureServices:

services.AddHttpContextAccessor();

См. Использование HttpContext из пользовательских компонентов для получения дополнительной информации об использовании IHttpContextAccessor.

Кирк Ларкин
источник
1
Спасибо за этот совет. Я пытаюсь создать политику, в которой при отсутствии ключа API вызов будет отклонен. Мы больше не можем использовать // Add Key Policy services.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (new AppKeyRequirement ()));}); Если нет, как я могу перехватить вызов, прежде чем он попадет в действие контроллера?
w2olves
1
Да, это все еще работает так же, как и раньше.
Кирк Ларкин
Конструктор ожидает IHttpContextAccessor, как я могу передать это, когда я создаю политику в Startup.cs? services.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (new AppKeyRequirement ()));}); Я также могу создать новый конструктор по умолчанию для AppKeyAuthorizationHandler, но затем httpContextAccessor.HttpContext; является нулевым, когда приходит запрос. Есть идеи?
w2olves
1
Вы добавляете ваш обработчик, используя DI, который создает его экземпляр для вас и передает в IHttpContextAccessor. Смотрите документы .
Кирк Ларкин