Asp.net core 如何在ASP.NETCore中组合/组合授权处理程序?
如何重复使用以组合两个处理程序Asp.net core 如何在ASP.NETCore中组合/组合授权处理程序?,asp.net-core,authorization,Asp.net Core,Authorization,如何重复使用以组合两个处理程序 RequirementA带有一个处理程序允许访问a:AuthorizationHandler RequirementB带有一个处理程序允许访问b:AuthorizationHandler 要求a\u或B如果满足则允许访问a或则允许访问B则成功 我的资源只有RequirementA和RequirementB可以访问。我也有可供A或B使用的资源 如果不复制IsAllowedAccessToA和IsAllowedAccessToB处理程序,我就不知道如何执行此操作
带有一个处理程序RequirementA
允许访问a:AuthorizationHandler
带有一个处理程序RequirementB
允许访问b:AuthorizationHandler
如果满足要求a\u或B
或则允许访问a
则成功则允许访问B
RequirementA
和RequirementB
可以访问。我也有可供A或B使用的资源
如果不复制IsAllowedAccessToA
和IsAllowedAccessToB
处理程序,我就不知道如何执行此操作
帮助,但不是完全相同的用例。让我们假设您的
需求a\u或B
由两个需求组成,例如:
公共类要求a\u或B:i授权要求
{
公共需求{get;set;}
公共要求b要求b{get;set;}
}
然后,您可以创建组合处理程序,如下所示:
public class RequirementA\u或BHandler:AuthorizationHandler
{
私人RequirementHandler _RequirementHandler;
私人需求Bhandler\u需求Bhandler;
公共需求a_或b Handler(/*任一处理程序所需的任何内容*/)
{
//注意:依赖注入框架可能会直接注入这两个处理程序,但我没有检查
_RequirementHandler=新的RequirementHandler();
_requirementBHandler=新requirementBHandler();
}
受保护的覆盖异步任务HandleRequirementAsync(授权HandlerContext上下文、RequirementA\u或B需求)
{
//创建一个包含两个需求的虚拟上下文
var要求=新的IAuthorizationRequirements[]
{
要求,要求,
要求,要求,
};
var dummyContext=新授权HandlerContext(需求,context.User,null);
wait_requirementHandler.HandleAsync(DummContext);
wait_requirementBHandler.HandleAsync(dummyContext);
//如果A或B成功,未决需求的数量将减少
if(dummyContext.PendingRequirements.Count()<2)
成功(要求);
等待任务。FromResult(true);
}
}
没有一种超级干净的方法可以将一个策略表示为其他两个策略之一
但您可以将其作为一个助手方法强制编写,以针对两个策略进行授权,您无法通过Authorize执行此操作,但您可以在需要时调用它:
async Task<bool> IsAllowedAccessToAOrB(ClaimsPrincipal user, IAuthorizationService auth, object resource) {
return await auth.AuthorizeAsync(user, resource, "PolicyA") || await auth.AuthorizeAsync(user, resource, "PolicyB")
}
异步任务被允许访问ORB(ClaimsPrincipal用户、IAAuthorizationService身份验证、对象资源){
返回wait auth.AuthorizeAsync(用户,资源,“策略A”)| wait auth.AuthorizeAsync(用户,资源,“策略B”)
}
事实上,你指的那篇文章给出了所有答案。您要做的唯一一件事是定义处理程序,使它们可以用于不同的需求,即使它们通用。稍后,您只需为每个需求使用不同的类型参数将它们注册为服务
因此,您的处理程序将类似于:
public class IsAllowedAccessToA<T>
: AuthorizationHandler<T> where T : IAuthorizationRequirement
{
}
公共类被允许访问a
:AuthorizationHandler,其中T:IAAuthorizationRequirement
{
}
您将注册它们以用于复合需求,如:
services.AddSingleton<IAuthorizationHandler, IsAllowedAccessToA<RequirementA_OR_B>>();
services.AddSingleton<IAuthorizationHandler, IsAllowedAccessToB<RequirementA_OR_B>>();
services.AddSingleton();
services.AddSingleton();
这应该可以满足您的需要。尝试以下方法:
您的需求类如下所示:
public class PermissionRequirement : IAuthorizationRequirement
{
public PermissionRequirement(string permission)
{
this.Permission = permission;
}
public string Permission { get; }
}
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly IPermissionProvider _permissionProvider;
private readonly IUserProvider _userProvider;
public PermissionAuthorizationHandler(IPermissionProvider permissionProvider, IUserProvider userProvider)
{
// permissionProvider is a class that has a function called hasClaim, with bool return value that takes user id and claim as input arguments and realize weather the user id has access to the controller or not
this._permissionProvider = permissionProvider;
// userProvider, return the id of current user
this._userProvider = userProvider;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
var hasClaim= await this._permissionProvider.HasClaim(this._userProvider.GetUserId(), requirement.Permission)
.ConfigureAwait(false);
if (hasClaim) context.Succeed(requirement);
else
context.Fail();
}
}
处理程序应该是这样的:
public class PermissionRequirement : IAuthorizationRequirement
{
public PermissionRequirement(string permission)
{
this.Permission = permission;
}
public string Permission { get; }
}
public class PermissionAuthorizationHandler : AuthorizationHandler<PermissionRequirement>
{
private readonly IPermissionProvider _permissionProvider;
private readonly IUserProvider _userProvider;
public PermissionAuthorizationHandler(IPermissionProvider permissionProvider, IUserProvider userProvider)
{
// permissionProvider is a class that has a function called hasClaim, with bool return value that takes user id and claim as input arguments and realize weather the user id has access to the controller or not
this._permissionProvider = permissionProvider;
// userProvider, return the id of current user
this._userProvider = userProvider;
}
protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, PermissionRequirement requirement)
{
var hasClaim= await this._permissionProvider.HasClaim(this._userProvider.GetUserId(), requirement.Permission)
.ConfigureAwait(false);
if (hasClaim) context.Succeed(requirement);
else
context.Fail();
}
}
公共类PermissionAuthorizationHandler:AuthorizationHandler
{
私有只读IPermissionProvider _permissionProvider;
专用只读IUserProvider\u用户提供程序;
公共PermissionAuthorizationHandler(IPermissionProvider permissionProvider、IUserProvider userProvider)
{
//permissionProvider是一个具有名为hasClaim的函数的类,其bool返回值将用户id和claim作为输入参数,并实现用户id是否可以访问控制器
此._permissionProvider=permissionProvider;
//userProvider,返回当前用户的id
这是.\u userProvider=userProvider;
}
受保护的重写异步任务HandleRequirementAsync(AuthorizationHandlerContext上下文,PermissionRequirementAsync)
{
var hasClaim=等待此。_permissionProvider.hasClaim(此。_userProvider.GetUserId(),requirement.Permission)
.配置等待(错误);
if(hasClaim)上下文成功(requirement);
其他的
context.Fail();
}
}