Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net core 如何在ASP.NETCore中组合/组合授权处理程序?_Asp.net Core_Authorization - Fatal编程技术网

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(); } }