【发布时间】: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