gpt4 book ai didi

c# - 为什么多次调用 app.UseEndpoints(..) 时中间件不执行?

转载 作者:行者123 更新时间:2023-12-03 08:50:30 33 4
gpt4 key购买 nike

我遇到过由于多次调用 app.UseEndpoints(...) 而跳过中间件的情况。

看看这个启动代码,我希望 SetUser() 中间件在 MVC Controller 之前执行。 HTTP request pipeline configuration

但是在调试时,断点永远不会被命中。

是否允许在应用程序的 HTTP 请求管道中的多个位置配置端点?如果是,为什么中间件没有执行?

要重现该问题,请创建一个新的 ASP.NET Core 3.1 MVC Web 应用程序。将 Startup.cs 替换为以下代码。然后给中间件设置断点,运行应用程序并确认中间件没有被执行。

using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace Carter50Repro
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}

public IConfiguration Configuration { get; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddHealthChecks();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapHealthChecks("/health");
});

app.Use(SetUser);
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}

private Task SetUser(HttpContext context, Func<Task> next)
{
context.User = new ClaimsPrincipal(new ClaimsIdentity(new Claim[]
{
new Claim(ClaimTypes.Name, "userId")
}, JwtBearerDefaults.AuthenticationScheme));
return next.Invoke();
}
}
}

我还在 ASP.NET Core 的 GitHub 页面 https://github.com/aspnet/AspNetCore/issues/17750 中将此问题作为问题发布

最佳答案

您似乎误解了端点路由的工作原理。端点路由运行两个中间件:路由中间件,由app.UseRouting()调用,端点中间件,由app.UseEndpoints(…).

路由中间件首先运行,它的工作本质上是找出正在请求的端点。它使用请求中的信息来解决这个问题。完成后,它会保存该信息以供以后使用。它实际上不会产生任何输出。

在路由中间件之后,您将需要运行其他可以利用端点信息的中间件。例如,授权中间件可以进行检查以确定用户是否有权访问所请求的端点。

最后,端点中间件运行。当它执行时,它将运行由路由中间件确定运行的端点。您在 UseEndpoints(…) 调用中配置的所有其他端点都将被忽略。

端点中间件通常被期望是最后运行的中间件,因为通常您希望它能够实际响应请求,无论系统请求什么(MVC、SignalR,等等)。

所以,是的,您可以多次使用UseEndpoints(…),但它可能不会执行您期望的操作。传递给 UseEndpoints 的所有配置委托(delegate)都会组合起来,以指定 UseRouting() 实际执行的操作。因此,对 UseEndpoints 的多次调用都只会配置该单个路由中间件。然后,当执行第一个端点中间件时,它将执行所请求的任何端点,无论该端点是否在确切的 UseEndpoints 调用中配置。

这意味着多次调用 UseEndpoints(…) 几乎总是表明您做错了什么。在您的情况下,通过拆分端点配置,您实际上无法拆分某些中间件需要完成的工作。因此,您的 SetUser 实际上永远不会为任一端点运行,因为它位于某些端点中间件之后。

如果您实际上想避免为某些路由调用 SetUser,那么您实际上应该利用端点路由为您提供的信息并让您的中间件有条件地运行。您可以获取determined Endpoint使用 httpContext.GetEndpoint(),然后浏览其元数据来决定是否需要执行某些操作。


综上所述,如果您的目标是使用给定身份对用户进行身份验证,那么您最好使用例如cookie 身份验证,然后直接登录主体。这样您就可以在身份验证堆栈之上进行构建。

关于c# - 为什么多次调用 app.UseEndpoints(..) 时中间件不执行?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59281967/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com