【问题标题】:.NET Core middleware invalidoperationexception.NET Core 中间件无效操作异常
【发布时间】:2021-03-06 18:25:00
【问题描述】:

我正在为 .NET Core 使用 hangfire 身份验证,当我在验证 .NET Core 时,红隼会抱怨无法设置 StatusCode,因为响应已经开始。有没有人遇到过类似的错误?

错误:

at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.ThrowResponseAlreadyStartedException(String name)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContext.Microsoft.AspNetCore.Http.Features.IHttpResponseFeature.set_StatusCode(Int32 value)
at Microsoft.AspNetCore.Http.DefaultHttpResponse.set_StatusCode(Int32 value)
at Hangfire.Dashboard.AspNetCoreDashboardMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Builder.Extensions.MapMiddleware.Invoke(HttpContext context)
at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Server.IIS.Core.IISHttpContextOfT`1.ProcessRequestAsync()

我最好的猜测是因为 Challenge 方法设置了状态码。这是设置 statusCode 的错误方式吗?

public bool Authorize(DashboardContext dashboardContext)
    {
        HttpContext context = dashboardContext.GetHttpContext();

        string header = context.Request.Headers["Authorization"];

        if (!string.IsNullOrWhiteSpace(header))
        {
            AuthenticationHeaderValue authValues = AuthenticationHeaderValue.Parse(header);

            if ("Basic".Equals(authValues.Scheme, StringComparison.InvariantCultureIgnoreCase))
            {
                string parameter = Encoding.UTF8.GetString(Convert.FromBase64String(authValues.Parameter));
                string[] parts = parameter.Split(':');

                if (parts.Length > 1)
                {
                    string username = parts[0];
                    string password = parts[1];

                    if ((!string.IsNullOrWhiteSpace(username)) && (!string.IsNullOrWhiteSpace(password)))
                    {
                        return Users.Any(user => user.ValidateUser(username, password)) || Challenge(context);
                    }
                }
            }
        }
        // ** The error appear when it return false
        return Challenge(context);
    }

    private static bool Challenge(HttpContext context)
    {
        context.Response.StatusCode = 401;
        context.Response.Headers.Append("WWW-Authenticate", "Basic realm=\"Hangfire Dashboard\"");

        context.Response.WriteAsync("Authentication is required.");

        return false;
    }

这就是我在启动时使用中间件的方式

public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env, IRecurringJobManager recurringJobManager)
{
   ...
   DashboardOptions options = new DashboardOptions
   {
        DashboardTitle = "Hangfire Scheduler",
        Authorization = new[] {
            new CustomAuthorizationFilter(new[]
            {
                // TODO: change to appsettings
                new HangfireUserCredentials
                {
                    Username = _configuration["Scheduler:username"],
                    Password = _configuration["Scheduler:password"]
                }
            })
        }
     };
     app.UseHangfireDashboard("/scheduler", options);
  ...
}

【问题讨论】:

  • 是的,StatusCode 必须在任何输出到响应之前设置,如错误消息所述,标题可能也是如此。
  • @schnitz77 嗯,我应该在哪里设置状态码?
  • 您发布的代码中似乎没有正确的位置,但必须在响应的任何输出之前设置它。
  • @schnitz77 根据我的跟踪信息,当指向hangfire仪表板时,它将有200响应,但它没有身份验证,因此在 (!string.IsNullOrWhiteSpace(header)) 它会检查httprequestheader中是否存在身份验证参数,如果不存在则将响应设置为401等。
  • 我明白了。状态 200 是默认值。如果您在设置 StatusCode 时遇到错误,您未在此处显示的内容已经修改了响应,对不起。

标签: c# asp.net-core hangfire asp.net-core-middleware


【解决方案1】:

我已经修复了我必须从启动中传递 httpcontext 的错误,否则 httpcontext 是默认的 httpcontext。

 DashboardOptions options = new DashboardOptions
 {
       DashboardTitle = "Markono Scheduler",
       IsReadOnlyFunc = (DashboardContext context) => !customAuthorizationFilter.Authorize(context),
 };

【讨论】:

    猜你喜欢
    • 2010-10-02
    • 1970-01-01
    • 1970-01-01
    • 2015-05-06
    • 1970-01-01
    • 2017-03-07
    • 2017-05-26
    • 1970-01-01
    相关资源
    最近更新 更多