首页 > 解决方案 > 中间件使用从客户端发送的参数,并根据这些参数允许或不允许与端点交互

问题描述

我正在使用c# core 3.1 我有几个端点,其结构类似于:

[HttpPost]
public async Task<ActionResult<Usuario>> Post([FromBody] User user) 
{
        context.User.Add(user);
        try
        {
             await context.SaveChangesAsync();
        }
        catch (Exception ex)
        {
           ...
        }
         return Ok();
}

用户发送这样的对象:

{"rol": "Administrator", "name":"pedro"}

我想验证它是否包含某个值,允许继续使用端点逻辑,否则不允许它。例如,我想验证是否rol= Administrator允许继续使用我的端点。

我很困惑,但我不知道是否存在这样的东西,但它作为一个中间件工作,我可以在其中获取从客户端发送的数据以执行验证:

[HttpPost]
[MyCustomMiddleWare]
.
.

public class MyCustomMiddleWare
{
 .
 .
 if (dataFromClientSide.rol== "Administrator")
 {
     continue
 }
 else{
   return Ok(new { message:"Not has permission" })
 } 
}

标签: c#

解决方案


看起来你只需要一些模型验证,如下所示:

using Microsoft.AspNetCore.Mvc;

using System.ComponentModel.DataAnnotations;
using System.Threading.Tasks;

[ApiController]
[Route("api/[controller]")]
public class YourController : ControllerBase
{
    public class User
    {
        [RegularExpression(pattern: "Administrator", ErrorMessage = "Your error message.")]
        public string Role { get; set; }

        public string Name { get; set; }
    }

    [HttpPost]
    public async Task<IActionResult> PostAsync([FromBody] User user)
    {
        if (this.ModelState.IsValid)
        {
            return this.ValidationProblem();
        }

        // Do something here;

        return this.Ok();
    }
}

那是无效角色的结果。

但如果你坚持使用中间件,它会如下所示:

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseMiddleware<UserRoleMiddleware>();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
        });
    }

    public class UserRoleMiddleware
    {
        private readonly RequestDelegate next;

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

        public async Task Invoke(HttpContext httpContext)
        {
            using var reader = new StreamReader(httpContext.Request.Body);

            var body = await reader.ReadToEndAsync();
            var user = JsonConvert.DeserializeObject<User>(body);

            if (user != null && !user.Role.Equals("Administrator", StringComparison.OrdinalIgnoreCase))
            {
                // Redirect or do somethings else.
            }

            await next(httpContext);
        }
    }

要验证特定的端点,只需实现 ActionFilterAttribute:

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddScoped<AdministratorAttribute>();
    }

    public class AdministratorAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext context)
        {
            if (context.ActionArguments.TryGetValue("user", out object user))
            {
                if (!(user as User).Role.Equals("Administrator"))
                {
                    // Redirect or something
                }
            }

            base.OnActionExecuting(context);
        }
    }

    [HttpPost]
    [Administrator]
    public async Task<IActionResult> PostAsync([FromBody] User user)
    {
        return this.Ok();
    }

推荐阅读