有没有办法将元数据添加到 ASP.NET Core 中的所有 GET 端点?
Posted
技术标签:
【中文标题】有没有办法将元数据添加到 ASP.NET Core 中的所有 GET 端点?【英文标题】:Is there a way to add metadata to all GET endpoints in ASP.NET Core? 【发布时间】:2022-01-19 18:01:41 【问题描述】:在以下语句中,AsBffApiEndpoint()
将属性添加到所有端点。然后有一个中间件专门寻找该属性,如果存在将检查是否存在防伪标头。
endpoints.MapControllers().RequireAuthorization().AsBffApiEndpoint();
我需要能够绕过对所有 GET 端点的检查。最重要的是,这是第三方库,因此我无法控制实现。
我尝试了很多事情都没有成功。最后一次尝试是添加一个中间件自定义中间件app.Use(...)
,如果该属性存在,则将其删除。但是这是不可能的,因为元数据列表是readonly
。然后,我最后的希望是找到一种方法将相同的属性添加到所有 GET 中,并带有一个忽略检查的标志 false
。换句话说,AsBffApiEndpoint()
所做的只是用[BffApi]
属性装饰一个端点。如果像 [BffApi(false)]
这样使用,此属性会忽略 antiforery 标头。我知道解决方案很老套,因为我最终会得到这样的结果。
[BffApi]
[BffApi(false)]
//endpoint definition here
好消息是他们获得了订购的端点元数据endpoint.Metadata.GetOrderedMetadata<BffApiAttribute>()
。这意味着只要[BffApi(false)]
在列表中占据优先级,我就应该很好。
【问题讨论】:
嗨@yopez83,你的AsBffApiEndpoint
是什么?你用过其他扩展吗?
@Rena 是 BFF 模式的实现。 github.com/DuendeSoftware/BFF
【参考方案1】:
我找到了解决方案,没有涉及添加第二个属性,而是扩展了构建器。这样我就可以修改端点元数据,此时它是可变的。
public static TBuilder AsBffApiEndpointBypassAntiforgeryOnGET<TBuilder>(this TBuilder builder, string routePrefix) where TBuilder : IEndpointConventionBuilder
builder.Add(endpointBuilder =>
var getAttribute = endpointBuilder.Metadata.FirstOrDefault(m => m.GetType() == typeof(HttpGetAttribute)) as HttpGetAttribute;
var routeAttribute = endpointBuilder.Metadata.FirstOrDefault(m => m.GetType() == typeof(RouteAttribute)) as RouteAttribute;
if (getAttribute != null && routeAttribute != null && routeAttribute.Template.StartsWith(routePrefix))
endpointBuilder.Metadata.Add(new BffApiAttribute(false));
else
endpointBuilder.Metadata.Add(new BffApiAttribute(true));
);
return builder;
然后在Startup.cs
app.UseEndpoints(endpoints =>
endpoints.MapBffManagementEndpoints();
endpoints.MapControllers().RequireAuthorization().AsBffApiEndpointBypassAntiforgeryOnGET("api/Foo");
);
更通用的实现如下。
public static IEndpointConventionBuilder AddConditionalMetadata(this IEndpointConventionBuilder builder, Func<EndpointBuilder, bool> evalEndpoint, Action<EndpointBuilder> onEvalTrue, Action<EndpointBuilder> onEvalFalse)
builder.Add(endpointBuilder =>
if (evalEndpoint.Invoke(endpointBuilder))
onEvalTrue.Invoke(endpointBuilder);
else
onEvalFalse.Invoke(endpointBuilder);
);
return builder;
通过这种方式,您可以公开要评估的功能和要执行的操作。然后,你的Startup.cs
会变成这个。
app.UseEndpoints(endpoints =>
endpoints.MapBffManagementEndpoints();
endpoints.MapControllers().RequireAuthorization().AddConditionalMetadata(
evalEndpoint: (endpointBuilder) =>
var routeAttribute = endpointBuilder.Metadata.FirstOrDefault(m => m.GetType() == typeof(RouteAttribute)) as RouteAttribute;
var getAttribute = endpointBuilder.Metadata.FirstOrDefault(m => m.GetType() == typeof(HttpGetAttribute)) as HttpGetAttribute;
return getAttribute != null && routeAttribute != null && routeAttribute.Template.StartsWith("api/Foo");
,
onEvalTrue: (endpointBuilder) => endpointBuilder.Metadata.Add(new BffApiAttribute(false)); ,
onEvalFalse: (endpointBuilder) => endpointBuilder.Metadata.Add(new BffApiAttribute()); );
);
我希望这可以帮助其他人寻找相同的东西。
【讨论】:
以上是关于有没有办法将元数据添加到 ASP.NET Core 中的所有 GET 端点?的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法在 Asp.Net Core Identity 中将 PasswordHash 的数据类型从字符串更改为字节数组
ASP.NET Core 3.1 - 将子项添加到剃刀局部视图
将动态添加的 html 表行作为参数发布到控制器 - ASP.NET Core/MVC
有没有办法为 ASP.NET Core 中的内容设置通用根路径?
如何使用 ASP.NET Core Identity 将登录/注册系统添加到现有数据库?
如何通过 IdentityServer4 将 OpenId Connect 添加到 ASP.NET Core 服务器端 Blazor Web 应用程序?