当前位置: 首页 > 知识库问答 >
问题:

DotNet核心中AuthorizationOptions需求的依赖注入

杨阳飇
2023-03-14

我有一个.NET core项目,并且正在尝试使用授权选项创建自定义策略,如此处的文档所示:

ASP.NET.Core授权-需求处理程序中的依赖注入

这些示例显示了使用 1 个参数(一个简单的 int 值)设置授权要求。我的自定义要求需要一个字符串参数以及一个 DbContext 对象。我想在运行时将 DbContext 注入到需求的构造函数中。我正在使用 Autofac 容器。我不确定如何实现这一目标 - 已经尝试了几种方法,到目前为止没有任何效果。

这是我的自定义要求:

public UserNameRequirement(string username, MyDbContext context)
{
    _userName = username;
    _dbContext = context;
}

在配置服务方法中设置Startup.cs授权选项时,留档会显示您这样注册:

services.AddAuthorization(options =>
{
    options.AddPolicy(
        "UserNamePolicy",
        policy => policy.Requirements.Add(new UserNameRequirement("admin", ** want to resolve and inject my DbContext here **)));
}

我不知道如何做到这一点。我看过这篇文章,这是一个类似的问题,但它使用的是 ASP.NET 5,并且语法不适用于.net core:

对授权选项的依赖注入

共有2个答案

薛栋
2023-03-14

您还可以使用 GetRequiredService 方法:

public class ExampleRequirement : AuthorizationHandler<ExampleRequirement>, IAuthorizationRequirement
{
    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, ExampleRequirement requirement)
    {
        UserManager<ApplicationUser> UserManager = ((ActionContext)context.Resource).HttpContext.RequestServices.GetRequiredService<UserManager<ApplicationUser>>();

        // you can work with the users ...      

        return Task.CompletedTask;
    }
}
贺高杰
2023-03-14

好的,我将在这里做一个假设,即您需要在UserNameRequirement中注入MyDbContext,以执行业务逻辑。

如果是这种情况,那么这意味着UserName必备既保存数据——在您的情况下是用户名——又保存授权逻辑。ASP.NETCore中的一个例子是ClaimsAuthorization必备

解决这个问题的方法是将其分为两类 - 一方面是仅保存与要求关联的数据的要求,另一方面是授权处理程序。请注意,即使我们将对其进行介绍,我所描述的内容也可以在官方 ASP.NET Core文档中找到。

因此,需求类可能如下所示:

public class UserNameRequirement : IAuthorizationRequirement
{
    public UserNameRequirement(string userName)
    {
        UserName = userName;
    }

    public string UserName { get; }
}

处理程序类将是:

public class UserNameRequirementHandler : AuthorizationHandler<UserNameRequirement>
{
    private readonly MyDbContext _dbContext;

    public UserNameRequirementHandler(MyDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, UserNameRequirement requirement)
    {
        var userName = requirement.UserName;

        // Use _dbContext to perform business logic
    }
}

下一步也是最后一步是在容器中注册处理程序:

services.AddSingleton<IAuthorizationHandler, UserNameRequirementHandler>();

这样做的效果是,您现在可以将需求添加到策略中,而不必担心DbContext

services.AddAuthorization(options =>
{
    options.AddPolicy(
        "UserNamePolicy",
        policy => policy.Requirements.Add(new UserNameRequirement("admin")));
}

在内部,ASP.NET将通过容器解析与该需求相关联的所有处理程序,因此< code>MyDbContext的实例将在处理程序中对您可用,允许您执行您认为合适的业务逻辑。

希望我的假设是正确的,这对你有所帮助。

编辑:

Henry Roux在下面的评论中提出了一个很好的观点,即如果UserName必需处理程序注册为单例,则将使用MyDbContext的单个实例,这可能会导致问题。确保您使用适当的生命周期注册您的授权处理程序。

 类似资料:
  • 如何在.NET核心库项目中将一个类注入另一个类?在API项目中的StartUp类ConfigureServices中,我应该在哪里配置DI?

  • 我的大多数服务通常与crud方法相同

  • 我有一个主要的ASP.NET核心Web API项目,它消耗多个项目,但我遵循清洁架构,所有接口都放在一个核心项目中,有模块项目(基础设施)定义实现。主要项目只是引用核心项目,而不知道基础设施。 这意味着我们需要扫描模块的依赖性,并用核心项目中定义的相应接口自动连接实现。 更具体地说,假设我有一个接口IA(在核心项目中)和一个实现A(在基础设施中),传统上,如果主项目同时引用两者,我们可以像这样手动

  • 我需要ASP。Net核心依赖注入,将一些参数传递给实现ICardPaymentRepository接口的GlobalRepositoryClass的构造函数。 参数是用于配置的,来自配置文件和数据库,我不希望我的类去引用数据库和配置本身。 我认为工厂模式是实现这一点的最佳方式,但我想不出使用工厂类的最佳方式。工厂类本身依赖于配置和数据库。 我的创业公司目前看起来像这样: GlobalReposit

  • 有谁知道我们可以下载jboss common core及其所有依赖项的存储库吗。依赖项是无法找到的。 我试过了http://mvnrepository.com/artifact/jboss/jboss-common-core/2.0.4.GA和https://repository.jboss.org/nexus/content/groups/public/jboss/jboss-common-co

  • 我试图从Azure函数调用存储库类,但遇到了一个错误 没有对应于形参的给定参数 我从. NET Core Web API项目中复制了存储库类结构,并且知道这与依赖注入有关。 repository类的构造函数如下所示: 我如何将其传递到Azure函数的静态方法中,就像我对Web API调用所做的那样,如下所示: