将过滤器参数传递给 DBContext
Pass Filter Parameter To DBContext
在 ASP.Net 核心 Web 应用程序中,将值传递给数据库上下文 class 以将其用作过滤器的正确方法是什么?
我需要过滤在我的 ASP.Net 核心网络应用的所有页面中返回的数据。过滤器将基于登录用户。如果登录用户来自 Branch 6108,那么他们应该只能看到该分支的数据。如果我使用原始值,我可以通过说
来过滤
modelBuilder.Entity<Branch>().HasQueryFilter(b => b.BranchID == 6108);
问题是我们有 50 多个分支机构,因此任何登录用户的数量都会不同。
所以理想情况下我想要它说
modelBuilder.Entity<Branch>().HasQueryFilter(b => b.BranchID == branchFilter);
其中 branchFilter 是我在使用
获取登录用户后发现并传递的值
@User.Identity.Name
当您启动 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
的实现上创建 public 属性 或方法,但您需要记住始终在查询任何数据集之前设置数据。这是一个极有可能的错误,具有相当大的后果,可以通过注入所需数据来避免。
有关此主题的完整指南,请阅读 Jon P. Smith 提出的设计:https://www.thereformedprogrammer.net/part-4-building-a-robust-and-secure-data-authorization-with-ef-core/
在 ASP.Net 核心 Web 应用程序中,将值传递给数据库上下文 class 以将其用作过滤器的正确方法是什么?
我需要过滤在我的 ASP.Net 核心网络应用的所有页面中返回的数据。过滤器将基于登录用户。如果登录用户来自 Branch 6108,那么他们应该只能看到该分支的数据。如果我使用原始值,我可以通过说
来过滤modelBuilder.Entity<Branch>().HasQueryFilter(b => b.BranchID == 6108);
问题是我们有 50 多个分支机构,因此任何登录用户的数量都会不同。
所以理想情况下我想要它说
modelBuilder.Entity<Branch>().HasQueryFilter(b => b.BranchID == branchFilter);
其中 branchFilter 是我在使用
获取登录用户后发现并传递的值@User.Identity.Name
当您启动 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
的实现上创建 public 属性 或方法,但您需要记住始终在查询任何数据集之前设置数据。这是一个极有可能的错误,具有相当大的后果,可以通过注入所需数据来避免。
有关此主题的完整指南,请阅读 Jon P. Smith 提出的设计:https://www.thereformedprogrammer.net/part-4-building-a-robust-and-secure-data-authorization-with-ef-core/