C# 中间件使用从客户端发送的参数,并根据这些参数允许或不允许与端点交互

C# 中间件使用从客户端发送的参数,并根据这些参数允许或不允许与端点交互,c#,C#,我正在使用c#core 3.1 我有几个端点的结构与此类似: [HttpPost] public async Task<ActionResult<Usuario>> Post([FromBody] User user) { context.User.Add(user); try { await context.SaveChangesAsync(); } catch

我正在使用
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
允许继续使用我的端点

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

[HttpPost]
[MyCustomMiddleWare]
.
.

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

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

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();
    }
}
使用Microsoft.AspNetCore.Mvc;
使用System.ComponentModel.DataAnnotations;
使用System.Threading.Tasks;
[ApiController]
[路由(“api/[控制器]”)]
公共类控制器:ControllerBase
{
公共类用户
{
[RegularExpression(模式:“管理员”,ErrorMessage=“您的错误消息”)]
公共字符串角色{get;set;}
公共字符串名称{get;set;}
}
[HttpPost]
公共异步任务PostAsync([FromBody]用户)
{
if(this.ModelState.IsValid)
{
返回此.ValidationProblem();
}
//在这里做点什么;
返回这个;
}
}

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

    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);
        }
    }
public void配置(IApplicationBuilder应用程序,IWebHostEnvironment环境)
{
app.UseMiddleware();
app.UseEndpoints(端点=>
{
endpoints.MapControllers();
});
}
公共类userrolemidware
{
私有只读请求委托下一步;
公共用户角色管理软件(RequestDelegate next)
{
this.next=next;
}
公共异步任务调用(HttpContext HttpContext)
{
使用var reader=newstreamreader(httpContext.Request.Body);
var body=wait reader.ReadToEndAsync();
var user=JsonConvert.DeserializeObject(主体);
if(user!=null&&!user.Role.Equals(“管理员”,StringComparison.OrdinalIgnoreCase))
{
//重定向或做其他事情。
}
等待下一步(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();
    }
public void配置服务(IServiceCollection服务)
{
services.addScope();
}
公共类管理属性:ActionFilterAttribute
{
公共重写无效OnActionExecuting(ActionExecutingContext上下文)
{
if(context.ActionArguments.TryGetValue(“用户”,out对象用户))
{
if(!(用户作为用户).Role.Equals(“管理员”))
{
//重定向什么的
}
}
base.OnActionExecuting(上下文);
}
}
[HttpPost]
[行政长官]
公共异步任务PostAsync([FromBody]用户)
{
返回这个;
}

太好了,我在找这样的东西。但是如何将其应用于某些端点而不是全部端点?谢谢!你能解释一下这个部分吗!(用户作为用户)在最后一段代码中,它是中间件吗?如果不满足条件,是否运行端点代码的其余部分?正在接收[frombody]吗?是的,此时接收到用户,但作为对象,将对象强制转换为用户或null,而不引发异常,您也可以执行类似的操作
!((用户作为用户)?.Role?.Equals(“管理员”)?false)
如果用户为null,但不应该是因为TryGetValue-它将返回false,并且不会进入其中
    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();
    }