简体   繁体   中英

ASP.NET Core: How would I go about binding data from user claims?

I have a simple ASP.NET Core http API, and there are an awful lot of controller actions that all start like this:

    public async Task<ActionResult> Delete()
    {
        if (!User.Claims.TryGetClaim("merchant_id", out long merchantId))
        {
            return BadRequest();
        }

        /* Real code using merchantId */
    }

I would like to reduce the duplication of the claims check each time, but I'm unsure how to go about it. I've got the code about as small as I can using just extension methods, but I'd like to get it smaller still, something like this:

public async Task<ActionResult> Delete([FromClaims] long merchantId)
{
    /* Real code using merchantId */
}

But I've been reading the docs on ASP.NET core middleware and I don't know what I have to implement to make this happen.

The built-in FromBody attribute inherits from IBindingSourceMetadata , which defines a BindingSource property. However, I can't find any resources online about how one might implement their own binding source to get items from the user claims.

You can use policy base authorization with attributes.

public void ConfigureServices(IServiceCollection services)
{
    ...
    services.AddAuthorization(options =>
    {
        options.AddPolicy("ShouldHaveMerchantId", policy => 
              policy.RequireClaim("merchant_id"));
    });
    ...
}

And on your action methods use Authorize attribute with your policy name.

[Authorize(Policy = "ShouldHaveMerchantId")]
public async Task<IActionResult> YourActionMethod()
{
    //Your logic
}

You could create a middleware like this

public class MyMiddleware 
{
   private readonly RequestDelegate next;

   public MyMiddleware (RequestDelegate next)
   {
        this.next = next;
   }

   public async Task Invoke(HttpContext ctx) 
   {
       // Your check here, something like
       if (!ctx.User.Claims.TryGetClaim("merchant_id", out long merchantId))
       {
            ctx.Response.StatusCode = (int)HttpStatusCode.BadRequest;
       }
       else
       {
            await next.Invoke(ctx);
       }

   }
}

and then register it like

app.UseMiddleware<MyMiddleware>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM