创建一个使用服务的新 AuthorizationHandler/IAuthorizationRequirement

Creating a new AuthorizationHandler/IAuthorizationRequirement that uses a service

我正在尝试创建一个新的授权要求,但它必须使用我在 ConfigureServices 中声明的服务之一,我不知道如何使用与声明服务。

public class NewRequirement: AuthorizationHandler<NewRequirement>, IAuthorizationRequirement
{
    private IRepository _repository;

    public NewRequirement(IRepository repository)
    {
        _repository = repository;
    }

    protected override void Handle(AuthorizationContext context, NewRequirement requirement)
    {
        //code that uses _repository here
    }
}

这很好用,但是当我尝试在 Startup.cs 中添加策略时,如下所示:

    public void ConfigureServices(IServiceCollection services)
    {
        ...

        services.AddSingleton<RepositoryContext>();
        services.AddScoped<IRepository, Repository>();

        services.Configure<AuthorizationOptions>(options =>
        {
            options.AddPolicy("NewRequirement", policy => policy.Requirements.Add(new NewRequirement()));
        });
    }

我收到这个错误

Error CS7036
There is no argument given that corresponds to the required formal parameter 'repository' of 'ExtraProjectRequirements.NewRequirement(IRepository)'
Reception.DNX 4.5.1

我想我需要将 IRepository 传递给新策略,但我不知道如何在 ConfigureServices 中进行。

您将处理程序传递给需求,这是错误的。 IAuthorizationRequirementAuthorizationHandler<NewRequirement> 需要是两个不同的 类。另外 IAuthorizationRequirement 只是一个标记接口 w/o 任何强制属性或方法,只是为了不小心将任意 类 添加到 Requirements 集合 ;)

IAuthorizationRequirement 将包含您的要求所需的纯数据(读取:没有服务,没有需要注入的依赖项),处理程序将对其进行验证。参见 example of an Over18Requirement and it's handler as well as the official documentation

允许处理程序注入依赖项。

供未来读者使用的文档中的示例(以防 link 变得不可用)。

public class MinimumAgeRequirement : IAuthorizationRequirement
{
    public MinimumAgeRequirement(int age)
    {
        MinimumAge = age;
    }

    protected int MinimumAge { get; set; }
}

public class MinimumAgeHandler : AuthorizationHandler<MinimumAgeRequirement>
{
    protected override void Handle(AuthorizationContext context, MinimumAgeRequirement requirement)
    {
        if (!context.User.HasClaim(c => c.Type == ClaimTypes.DateOfBirth &&
                                   c.Issuer == "http://contoso.com"))
        {
            return;
        }

        var dateOfBirth = Convert.ToDateTime(context.User.FindFirst(
            c => c.Type == ClaimTypes.DateOfBirth && c.Issuer == "http://contoso.com").Value);

        int calculatedAge = DateTime.Today.Year - dateOfBirth.Year;
        if (dateOfBirth > DateTime.Today.AddYears(-calculatedAge))
        {
            calculatedAge--;
        }

        if (calculatedAge >= requirement.MinimumAge)
        {
            context.Succeed(requirement);
        }
    }
}

不确定这是否真的是您要查找的内容,但请先尝试获取 IRepository 实例,然后将其传递给 NewRequirement class

var repo = services
                .BuildServiceProvider()
                .GetRequiredService<IRepository>();

    services.Configure<AuthorizationOptions>(options =>
    {
        options.AddPolicy("NewRequirement", 
                policy => policy.Requirements.Add(new NewRequirement(repo)));
    });