将参数传递给 MVC 6 ASP.NET 中的要求/策略
本文关键字:策略 NET 参数传递 MVC ASP | 更新日期: 2023-09-27 18:09:25
我试图在 vNext 中创建自定义授权属性 ASP.NET 直到我在这篇文章中找到了@blowdart的这个很好的答案:
https://stackoverflow.com/a/31465227/1756978
表明授权要求现在是要走的路。答案非常明确,但没有指示如何将参数传递给此要求/策略。
我正在尝试做的是移植具有以下签名的 MVC 5 自定义授权属性:
[Autorizacion(Requires = enumPermission.DeleteCustomer)]
因为我使用一组非常自定义的权限作为枚举/字符串镜像在后端/前端。
由于此功能仍未记录在案,我感到有点迷茫......有人可以给出指导吗?
提前致谢
我碰巧想出了一个可以满足我要求的解决方法,希望它也能对您有所帮助。
就我而言,我需要将IHttpContextAccessor
和 EFCore 的AppDbContext
传递给我的要求类。
在我的Startup.cs
,我写了这样的东西:
services.AddAuthorization(options =>
{
options.AddPolicy("ThePolicy", policy => policy.Requirements.Add( new ThePolicyRequirement() ));
});
services.AddScoped<IAuthorizationHandler, ThePolicyAuthorizationHandler>();
ThePolicyAuthorizationHandler
类:
public class ThePolicyAuthorizationHandler : AuthorizationHandler<ThePolicyRequirement>
{
readonly AppDbContext _appContext;
readonly IHttpContextAccessor _contextAccessor;
public ThePolicyAuthorizationHandler(AppDbContext c, IHttpContextAccessor ca)
{
_appContext = c;
_contextAccessor = ca;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ThePolicyRequirement requirement)
{
var result = await requirement.isPass(_appContext, _contextAccessor, context);
if (result)
context.Succeed(requirement);
else
context.Fail(requirement);
}
}
和ThePolicyRequirement
类:
public class ThePolicyRequirement : IAuthorizationRequirement
{
AppDbContext _context;
IHttpContextAccessor _contextAccessor;
AuthorizationHandlerContext _authHandlerContext;
public async Task<bool> isPass(AppDbContext context, IHttpContextAccessor contextAccessor, AuthorizationHandlerContext authorizationHandlerContext)
{
_context = context;
_contextAccessor = contextAccessor;
_authHandlerContext = authorizationHandlerContext;
//logic here
return result;
}
}
关键思想是使用ThePolicyAuthorizationHandler
尽可能多地获取所有需要的对象,并将其传递给ThePolicyRequirement
来做授权机制的逻辑。
确实,@blowdart的帖子非常有见地,根据我的理解,要理解的关键是以下几点:
授权作用于标识。标识由 认证。
因此,身份似乎是由身份验证过程创建的。
然后(如果您愿意(您可以启动授权过程。这意味着创建一个自定义authorization requirements
,此要求将查看这些标识并对其执行操作。
用简单的英语来说,这就是我认为正在发生的事情:
-
正如 blowdart 的帖子中提到的,我们应该有某种碰巧执行实际操作的身份验证中间件认证。成功通过身份验证后,您可以采取任何措施您希望从该现已通过身份验证的用户那里获得的信息,并创建一个经过身份验证的
ClaimsPrincipal
。例如,我们可以存储到该
ClaimsPrincipal
中,将用户拥有的权限。 -
然后,当您创建
authorization requirement
时,您会查看ClaimsPrincipal
,从ClaimsPrincipal
并根据任何因素采取适当的行动所需的业务规则。假设您无法将权限集存储到
ClaimsPrincipal
由于某种原因,可以轻松存储UserId并从要求中读取该用户ClaimsPrincipal
,调用数据库并获取权限集然后对它们采取行动。
结论:
所以简而言之,我不认为你把东西传递给要求,我认为你从ClaimsPrincipal
内获得它们。
在您的示例中,您可以创建一个要求来读取ClaimsPrincipal
并将任何值与您的Enum
进行比较,并据此采取行动。
让我们知道您设法做了什么以及它是否有效。
如果我对此的理解是错误的,那么无论如何,请随时纠正我,因为所有这些都是新事物:-(