c# - 在 netcore api 3.1 中读取 AuthorizationFilterContext
问题描述
我有一个工作的 netcore 2.2 项目,我在其中实施了一个检查 API 密钥的自定义策略。
在 startup.cs 我正在添加这样的策略
//Add Key Policy
services.AddAuthorization(options =>
{
options.AddPolicy("AppKey", policy => policy.Requirements.Add(new AppKeyRequirement()));
});
在我的 AppKeyRequirement 中,我从 AuthorizationHandler 继承并解析传入请求中的密钥,如下所示
protected override Task HandleRequirementAsync(AuthorizationHandlerContext authContext, AppKeyRequirement requirement)
{
var authorizationFilterContext = (AuthorizationFilterContext)authContext.Resource;
var query = authorizationFilterContext.HttpContext.Request.Query;
if (query.ContainsKey("key") && query.ContainsKey("app"))
{ // Do stuff
这在 netcore 3.1 中不起作用
我收到以下错误:
无法将类型为“Microsoft.AspNetCore.Routing.RouteEndpoint”的对象转换为类型“Microsoft.AspNetCore.Mvc.Filters.AuthorizationFilterContext”。
在核心 3 及更高版本中执行此操作的正确方法是什么?
正如 Kirk Larkin 所指出的,.net 3.0 及更高版本中的正确方法是将 IHttpContextAccessor 注入 Auth 处理程序并使用它。
我此时的问题是如何注入这个?我无法在 startup.cs 中传递它,或者至少我没有看到如何传递。
任何想法/提示将不胜感激。
解决方案
ASP.NET 核心 5.x
根据ASP.NET Core 5.0-preview7 及更高版本的公告Resource
,该属性设置HttpContext
为请求的当前值(使用终结点路由时)。这意味着以下示例将适用于 ASP.NET Core 5.0 及更高版本,而无需IHttpContextAccessor
:
public class AppKeyAuthorizationHandler : AuthorizationHandler<AppKeyRequirement>
{
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext authContext, AppKeyRequirement requirement)
{
var httpContext = authContext.Resource as HttpContext;
var query = httpContext.Request.Query;
if (query.ContainsKey("key") && query.ContainsKey("app"))
{
// ...
}
}
}
RouteEndpoint
仍然可用,使用httpContext.GetEndpoint()
.
ASP.NET 核心 3.x
在 ASP.NET Core 3.0 之前的版本中,IAuthorizationHandler
在 MVC 管道期间调用 的实现。从 3.0 开始,它使用端点路由(默认情况下),这些实现由授权中间件 ( UseAuthorization()
) 调用。这个中间件在 MVC 管道之前运行,而不是作为它的一部分。
此更改意味着AuthorizationFilterContext
不再传递给授权处理程序。相反,它是 的一个实例RouteEndpoint
,它不提供对HttpContext
.
在您的示例中,您仅AuthorizationFilterContext
用于获取HttpContext
. 在 3.0+ 中,注入IHttpContextAccessor
您的授权处理程序并使用它。这是一个完整性示例:
public class AppKeyAuthorizationHandler : AuthorizationHandler<AppKeyRequirement>
{
private readonly IHttpContextAccessor httpContextAccessor;
public AppKeyAuthorizationHandler(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
protected override Task HandleRequirementAsync(
AuthorizationHandlerContext authContext, AppKeyRequirement requirement)
{
var httpContext = httpContextAccessor.HttpContext;
var query = httpContext.Request.Query;
if (query.ContainsKey("key") && query.ContainsKey("app"))
{
// ...
}
}
}
您可能还需要IHttpContextAccessor
注册ConfigureServices
:
services.AddHttpContextAccessor();
有关使用IHttpContextAccessor
. _