【问题标题】:How do I stop my .NET CORE API Custom middleware from being ignored如何阻止我的 .NET CORE API 自定义中间件被忽略
【发布时间】:2020-02-26 07:16:29
【问题描述】:

当 API 收到消息时,我的 .NET CORE API 自定义中间件被忽略。此中间件旨在对任何给定请求执行一些标头验证。

我希望标头验证中间件作为请求的一部分被调用,以便 header.isValid 显示此验证的结果。当我在控制器中放置断点时,标头变量为空。

我是否误解了中间件在期望它与控制器通信时可以做什么?我需要它做的就是充当对不良请求的看门人,因此我愿意让它终止不良请求并允许好的请求通过作为结果。

这就是我所拥有的

    public interface IHeaderIsValid
    {
        bool isValid { get; set; }
        bool fromCMDS { get; set; }
        bool fromLocal { get; set; }
        Int16 transmittingInstallationID { get; set; }
    }

    public class HeaderIsValid : IHeaderIsValid
    {
        public bool  isValid { get; set; }
        public bool fromCMDS { get; set; }
        public bool fromLocal { get; set; }
        public Int16 transmittingInstallationID { get; set; }

    }
    public static class RequestHeaderMiddlewareExtensions
    {
        public static IApplicationBuilder UseHeaderValidation(this IApplicationBuilder app)
        {
            return app.UseMiddleware<RequestHeaderMiddleware>();
        }
    }

    public class RequestHeaderMiddleware
    {

        #region CONSTRUCTORS

        /// <summary>
        /// The Request header middleware constructor
        /// </summary>
        /// <param name="next">navigation parameter to pass the request to the next pipeline item</param>
        public RequestHeaderMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        #endregion


        #region PUBLIC METHJODS

        /// <summary>
        /// Invoke the middleware to validate the request header
        /// </summary>
        /// <param name="context">the context of the request</param>
        /// <returns>true or throws an exception</returns>
        public async Task Invoke(HttpContext context, IHeaderIsValid header)
        {
            try
            {
                header.isValid = false;
                bool hasInstallationID = Int16.TryParse(context.Request.Headers.FirstOrDefault(x => x.Key == "InstallationID").Value.ToString(), out this.transmittingInstallationID);
                if (!hasInstallationID)
                {
                    throw new NoInstallationIDOnHeaderException("No Installation ID on the Request Header");
                }

                string fromLocalHeader = context.Request.Headers.FirstOrDefault(x => x.Key == "FromLocal").Value.ToString();
                if (fromLocalHeader != string.Empty)
                {
                    bool.TryParse(fromLocalHeader, out this.fromLocal);
                }
                else
                {
                    this.fromLocal = false;
                }

                bool hasFromCMDS = bool.TryParse(context.Request.Headers.FirstOrDefault(x => x.Key == "FromCMDS").Value.ToString(), out this.fromCMDS);
                if (!hasFromCMDS)
                {
                    this.fromCMDS = false;
                }

                if (this.fromCMDS && this.fromLocal)
                {
                    throw new FromCMDSAndFromLocalSetException("The FromLocal and FromCMDS indicators are both set on the request header");
                }

                if (!this.fromCMDS && !this.fromLocal)
                {
                    throw new NoOriginSetException("One of The FromLocal and FromCMDS indicators must be set on the request header");
                }

            }
            catch (Exception ex)
            {
                throw ex;
            }

           header.isValid = true;

            await _next(context);
        }

        #endregion


        #region PRIVATE VARIABLES

        private readonly RequestDelegate _next;

        #endregion


        #region PUBLIC VARIABLES

        public Int16 transmittingInstallationID;
        public bool fromCMDS;
        public bool fromLocal;

        #endregion
    }

然后在 startup.cs 中(为简洁起见,对 ConfigurationServices 进行了修剪)

        public void ConfigureServices(IServiceCollection services)
        {
            services.AddScoped<IHeaderIsValid, HeaderIsValid>();
            services.AddMvcCore()
                .AddAuthorization()
                .AddJsonFormatters();

        }


       public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddLog4Net();

            app.UseCors("default");
            app.UseAuthentication();
            app.UseMvc();

            // My custom middleware to validate the header
            app.UseHeaderValidation();
        }
    }
}

这是来自控制器的 sn-p:

    [Route("LDH/[controller]")]
    [ApiController]
    public class SalesController : ControllerBase
    {
      [Authorize]
        [HttpPost("ProcessPayment")]
        public async Task<ActionResult> ProcessPayment(WorkingTicket ticketDetails)
        {
            if (!header.isValid)
            {
                ModelState.AddModelError("BadHeader", "Request header is invalid");
                return BadRequest(ModelState);
            }
            Return OK();
        }

        private IHeaderIsValid header;
    }

【问题讨论】:

  • 在您的 Configure 方法中,您定义了一个管道,目前是 HTTP 请求 -> Cors -> Auth -> MVC(完成所有控制器的工作)-> 响应模型 -> Auth -> Cors - > HTTP 响应。管道中的每个中间件都可以选择不调用下一个委托,例如当凭据不匹配并且 MVC 永远不会调用下一个委托时进行身份验证。因此,您需要将中间件放在 MVC 之前。
  • 通过在Configure()method 顺序中设置管道很重要。所以你应该在UseMvc() 之前移动UseHeaderValidation()。根据您的期望,您可能还应该在 UseAuthentication() 之前移动它。
  • 就是这样。非常赞赏。

标签: c# asp.net-mvc asp.net-web-api


【解决方案1】:

添加 app.UseHeaderValidation();到 Configure() 的开头。

【讨论】:

    猜你喜欢
    • 2021-05-11
    • 2018-04-12
    • 1970-01-01
    • 2021-08-03
    • 1970-01-01
    • 2019-07-01
    • 2010-09-10
    • 1970-01-01
    • 2020-08-29
    相关资源
    最近更新 更多