Lendo o AuthorizationFilterContext no netcore api 3.1

9

Eu tenho um projeto netcore 2.2 em funcionamento em que implementei uma política personalizada que verifica as chaves da API.

No startup.cs, estou adicionando esta política como esta

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

No meu AppKeyRequirement, herdo de AuthorizationHandler e resolvo as chaves nas solicitações de entrada como esta

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

Isso não funciona no netcore 3.1

Eu estou recebendo o seguinte erro:

Não foi possível converter o objeto do tipo 'Microsoft.AspNetCore.Routing.RouteEndpoint' para digitar 'Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext'.

Qual é a maneira correta de fazer isso no núcleo 3 e acima?

Conforme apontado por Kirk Larkin, a maneira correta no .net 3.0 e acima é injetar IHttpContextAccessor no manipulador Auth e usá-lo.

A minha pergunta neste momento é como injetar isso? Não posso passar isso no startup.cs ou pelo menos não estou vendo como.

Todas as idéias / sugestões serão muito apreciadas.

w2olves
fonte

Respostas:

14

Nas versões anteriores ao ASP.NET Core 3.0, as implementações de IAuthorizationHandlereram chamadas durante o pipeline do MVC. No 3.0 em diante, que usa o roteamento de terminal (por padrão), essas implementações são chamadas pelo middleware de autorização ( UseAuthorization()). Esse middleware é executado antes do pipeline MVC, e não como parte dele.

Essa alteração significa que AuthorizationFilterContextnão é mais passada para os manipuladores de autorização. Em vez disso, é uma instância de RouteEndpoint, que não fornece acesso ao HttpContext.

No seu exemplo, você está usando apenas AuthorizationFilterContextpara se apossar HttpContext. No 3.0+, injete IHttpContextAccessorem seu manipulador de autorização e use-o. Aqui está um exemplo de integridade:

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

Você também pode precisar se registrar IHttpContextAccessorem ConfigureServices:

services.AddHttpContextAccessor();

Consulte Usar HttpContext de componentes personalizados para obter mais informações sobre como usar IHttpContextAccessor.

Kirk Larkin
fonte
11
Obrigado por esta dica. Estou tentando criar uma política em que, se uma chave de API estiver ausente, a chamada será rejeitada. Não podemos mais usar // Adicionar serviços de Política de Chave.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (new AppKeyRequirement ()));}); Caso contrário, como posso interceptar uma chamada antes que ela atinja uma ação do controlador?
W2olves 27/10/19
11
Sim, isso ainda funciona da mesma maneira que antes.
Kirk Larkin
O construtor está esperando IHttpContextAccessor, como posso passar isso quando crio a política no Startup.cs? services.AddAuthorization (options => {options.AddPolicy ("AppKey", policy => policy.Requirements.Add (new AppKeyRequirement ()));}); Também posso criar um novo construtor padrão para AppKeyAuthorizationHandler, mas depois httpContextAccessor.HttpContext; é nulo quando uma solicitação é recebida. Alguma idéia?
W2olves 27/10/19
11
Você adiciona seu manipulador usando o DI, que cria uma instância para você e passa no IHttpContextAccessor. Veja os documentos .
21419 Kirk Larkin