【问题标题】:Pass Filter Parameter To DBContext将过滤器参数传递给 DBContext
【发布时间】:2021-12-02 23:50:18
【问题描述】:

在 ASP.Net Core Web 应用程序中,将值传递给 DB Context 类以将其用作过滤器的正确方法是什么?

我需要过滤在我的 ASP.Net Core Web 应用程序的所有页面中返回的数据。过滤器将基于登录的用户。如果登录用户来自分支 6108,那么他们应该只能看到该分支的数据。如果我使用原始值,我可以说

modelBuilder.Entity<Branch>().HasQueryFilter(b => b.BranchID == 6108);

问题是我们有 50 多个分支机构,因此任何登录用户的数量都会有所不同。

所以我希望它说出来

modelBuilder.Entity<Branch>().HasQueryFilter(b => b.BranchID == branchFilter);

其中 branchFilter 是我使用获取登录用户后发现并传递的值

@User.Identity.Name

【问题讨论】:

  • 将branchFilter 设为DbContext 的属性/字段。请参阅带有 _tenantId 的 Global Query Filter 示例

标签: c# asp.net-core entity-framework-core razor-pages dbcontext


【解决方案1】:

当您启动 DbContext 时,您可以注入所需的用户数据,将其存储在一个字段中,然后在您的查询中使用它。为此,您可以为此用户数据创建一个接口,然后通过依赖注入注入用户数据的实现。之后,您可以使用 HasQueryFilter 中的字段。

例如:

public class YourDbContext : DbContext
{
    private string branchId;
    private string userId;


    public YourDbContext(DbContextOptions<YourDbContext> options, IGetUserProvider userData) : base(options)
    {          
        tenantId = userData.BranchId;
        userId = userData.UserId;
    }
// ...
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Branch>().HasQueryFilter(b => b.BranchID == branchId);
    }
}

还有一个关于如何从 HttpContext 获取用户的示例,您的用户在其中拥有对分支的声明。您当然应该有一个与您的用例相关的IGetUserProvider 实现。

public interface IGetUserProvider
{
    string UserId { get; }
    string BranchId { get; }
}

public class GetUserProvider : IGetUserProvider
{
    public string UserId { get; }
    public string BranchId { get; }

    public GetTenantClaimsProvider(IHttpContextAccessor accessor)
    {
        UserId = accessor.HttpContext?.User.Claims.SingleOrDefault(x => x.Type == UserIdentifierClaimName)?.Value;
        BranchId = accessor.HttpContext?.User.Claims.SingleOrDefault(x => x.Type == BranchIdentifierClaimName)?.Value;
    }
}

或者,您可以在 DbContext 的实现上创建公共属性或方法,但您需要记住始终在查询任何数据集之前设置数据。这是一个极有可能的错误,会产生相当大的后果,可以通过注入所需的数据来避免。

有关此主题的完整指南,请阅读 Jon P. Smith 提出的设计:https://www.thereformedprogrammer.net/part-4-building-a-robust-and-secure-data-authorization-with-ef-core/

【讨论】:

  • 非常感谢您的帮助,但它导致了一个额外的问题,我已将其添加到原始帖子中,如果您能提供任何见解,我将不胜感激。
  • 我不熟悉您新建 DbContext 的模式,我想知道这是否与您代码中其他地方的模式不同(我希望您在需要的地方注入您的 DbContext)。在我看来,当您新建 TimeSheetContext 时,config 丢失了,但使用有限的代码很难理解。
  • 感谢@Superman.Lopez,编辑中的问题与您的解决方案无关。您的建议确实解决了问题。
猜你喜欢
  • 2016-04-17
  • 2012-07-29
  • 2013-08-17
  • 2018-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多