gpt4 book ai didi

asp.net - 在 ASP.NET 5 中,如何在中间件中获取所选路由?

转载 作者:行者123 更新时间:2023-12-04 04:30:02 24 4
gpt4 key购买 nike

我正在构建一个 ASP.NET 5 (vNext) 站点,它将托管动态页面、静态内容和 REST Web API。我找到了如何使用新的 ASP.NET 做事方式创建中间件的示例,但我遇到了障碍。

我正在尝试编写自己的身份验证中间件。我想创建一个自定义属性以附加到指定它需要身份验证的 Controller 操作(或整个 Controller )。然后在请求期间,在我的中间件中,我想将需要身份验证的操作列表与适用于当前请求的操作交叉引用。据我了解,我在 MVC 中间件之前配置了我的中间件,以便在管道中首先调用它。我需要这样做,以便在 MVC Controller 处理请求之前完成身份验证,这样我就无法阻止 Controller 在必要时被调用。但这不也意味着MVC路由器还没有确定我的路由吗?在我看来,路线的确定和路线行动的执行是在管道中的一步发生的,对吗?

如果我希望能够确定请求是否与 Controller 处理请求之前发生的中间件管道步骤中的 Controller 操作匹配,我是否必须编写自己的 url 解析器来解决这个问题?在 Controller 实际处理请求之前,是否有某种方法可以获取请求的路由数据?

编辑:我开始认为 RouterMiddleware可能是我正在寻找的答案。我假设我可以弄清楚如何让我的路由器选择标准 MVC 路由器正在使用的相同路由(我使用属性路由)并让我的路由器(真正的身份验证器)在它成功验证时将请求标记为未处理所以默认的 mvc 路由器执行实际的请求处理。我真的不想完全实现 MVC 中间件正在做的所有事情。努力试图弄清楚。 RouterMiddleware有点向我展示了我认为我需要做什么。

编辑 2:这是 ASP.NET 5 中的中间件模板

public class TokenAuthentication
{
private readonly RequestDelegate _next;

public TokenAuthentication(RequestDelegate next)
{
_next = next;
}

public async Task Invoke(HttpContext context)
{
//do stuff here

//let next thing in the pipeline go
await _next(context);

//do exit code
}
}

最佳答案

我最终查看了 ASP.NET 源代码(因为它现在是开源的!),发现我可以从 this class 复制 UseMvc 扩展方法。并为我自己的默认处理程序换掉。

public static class TokenAuthenticationExtensions
{
public static IApplicationBuilder UseTokenAuthentication(this IApplicationBuilder app, Action<IRouteBuilder> configureRoutes)
{
var routes = new RouteBuilder
{
DefaultHandler = new TokenRouteHandler(),
ServiceProvider = app.ApplicationServices
};

configureRoutes(routes);

routes.Routes.Insert(0, AttributeRouting.CreateAttributeMegaRoute(
routes.DefaultHandler,
app.ApplicationServices));

return app.UseRouter(routes.Build());
}
}

然后创建自己的 this class 版本.就我而言,我实际上并不想调用这些操作。我会让典型的 Mvc 中间件来做。既然是这种情况,我就消化了所有相关的代码,并保留了获取 中的路线数据所需的内容。 Action 描述符 多变的。我可能可以删除处理备份路线数据的代码,因为我认为我将做的事情不会影响数据,但我将其保留在示例中。这是我将开始基于 mvc 路由处理程序的框架。
public class TokenRouteHandler : IRouter
{
private IActionSelector _actionSelector;

public VirtualPathData GetVirtualPath(VirtualPathContext context)
{
EnsureServices(context.Context);

context.IsBound = _actionSelector.HasValidAction(context);

return null;
}

public async Task RouteAsync(RouteContext context)
{
var services = context.HttpContext.RequestServices;

EnsureServices(context.HttpContext);

var actionDescriptor = await _actionSelector.SelectAsync(context);
if (actionDescriptor == null)
{
return;
}

var oldRouteData = context.RouteData;
var newRouteData = new RouteData(oldRouteData);

if (actionDescriptor.RouteValueDefaults != null)
{
foreach (var kvp in actionDescriptor.RouteValueDefaults)
{
if (!newRouteData.Values.ContainsKey(kvp.Key))
{
newRouteData.Values.Add(kvp.Key, kvp.Value);
}
}
}

try
{
context.RouteData = newRouteData;

//Authentication code will go here <-----------
var authenticated = true;

if (!authenticated)
{
context.IsHandled = true;
}
}
finally
{
if (!context.IsHandled)
{
context.RouteData = oldRouteData;
}
}
}

private void EnsureServices(HttpContext context)
{
if (_actionSelector == null)
{
_actionSelector = context.RequestServices.GetRequiredService<IActionSelector>();
}
}
}

最后,在管道末尾的 Startup.cs 文件的 Configure 方法中,我对其进行了设置,以便我对 token 身份验证和 mvc 路由器使用相同的路由设置(我使用属性路由)。
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
//Other middleware delcartions here <----------------

Action<IRouteBuilder> routeBuilder = routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
};

app.UseTokenAuthentication(routeBuilder);

//Middleware after this point will be blocked if authentication fails by having the TokenRouteHandler setting context.IsHandled to true

app.UseMvc(routeBuilder);
}

编辑1:
我还应该注意,目前我并不担心两次选择路线所需的额外时间,这是我认为在这里会发生的事情,因为我的中间件和 Mvc 中间件都会这样做。如果这成为性能问题,那么我会将 mvc 和身份验证构建到一个处理程序中。这在性能方面是最好的主意,但我在这里展示的是我认为最模块化的方法。

编辑2:
最后,为了获得我需要的信息,我必须将 ActionDescriptor 转换为 ControllerActionDescriptor。我不确定您可以在 ASP.NET 中执行哪些其他类型的操作,但我很确定我的所有操作描述符都应该是 ControllerActionDescriptors。也许旧的遗留 Web Api 东西需要另一种类型的 ActionDescriptor。

关于asp.net - 在 ASP.NET 5 中,如何在中间件中获取所选路由?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32022266/

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