首页 > 解决方案 > What is the proper way of getting the HTTP request method in an AuthorizationHandler?

问题描述

Simplified version of what I'm trying to do: I want to write an authorization policy that will block requests that aren't GET if a flag is set in the database. I registered my policy, the handler code runs fine for my controller, but I'm not sure what the best way of getting the HTTP method type is.

Controller looks like this:

[Authorize(Policy = "Test")]
public class MyController : ControllerBase
{
    // ...
}

My handler looks like this:

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext ctx, MyRequirement req)
{
    // Fetch some flag from db

    if (!flag)
    {
        ctx.Succeed(req);
        return;
    }

    var method = GetRequestMethodFromCtx(ctx.Resource);

    if (method == HttpMethods.Get)
    {
        ctx.Succeed(req);
    }
    else
    {
        ctx.Fail();
    }
}

I noticed that for a single request my handler gets called multiple times and that ctx.Resource is not always the same type. First time it is a RouteEndpoint, after which it is an AuthorizationFilterContextSealed.

Should I just extract the HTTP method from the RouteEndpoint and ignore the second call? Also, why are there multiple calls to the handler?

标签: c#asp.net-coreasp.net-core-3.1.net-core-3.1

解决方案


In order to access to HttpContext object you can use the IHttpContextAccessor service.

You can simply require it as a dependency of your authorization handler class and the ASP.NET core dependency injection will provide the service for you.

In order to register it with the dependency injection you need to call services.AddHttpContextAccessor() in the ConfigureServices method of your Startup class.

From the HttpContext you will have access to the Request and then to the Method property (see here).

Refer to the official documentation for the details.

I don't know exactly your requirements, but in order to prevent an action method being called with a specific HTTP verb there is a much simpler way. You just need to use the built in routing attributes, you can find more information here.


推荐阅读