DbContext模型构建器中的用户详细信息
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DbContext模型构建器中的用户详细信息相关的知识,希望对你有一定的参考价值。
我是razor pages / efcore / aspnet身份的新手,并且一直试图解决这个问题,但它击败了我。
基本上,我使用AspNet Identity进行用户身份验证和授权。我已经使用额外的OrganisationId扩展了AspNetUsers,这是一个组织实体的FK;并在身份声明商店中添加了ID作为声明。这很好用。
现在,我需要根据经过身份验证的用户的organisationId设置efcore global filter,以便他们只能查看分配给其组织的数据。
但是,我无法访问模型构建器中经过身份验证的用户详细信息。
public class SDMOxContext : IdentityDbContext<
ApplicationUser, ApplicationRole, string,
ApplicationUserClaim, ApplicationUserRole, ApplicationUserLogin,
ApplicationRoleClaim, ApplicationUserToken>
{
public SDMOxContext(DbContextOptions<SDMOxContext> options)
: base(options)
{ }
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
// Set global filter so users can only see projects within their organisation.
builder.Entity<Project>().HasQueryFilter(project => project.OrganisationId == 1);
}
我需要输入用户organisationid而不是全局过滤器中的1,而用户声明存储为用户声明。通常我得到它:
User.FindFirstValue("OrganisationId")
但是,用户在当前上下文中不存在。
所以我需要在稍后阶段应用查询过滤器,即。用户认证后?从中间层/逻辑层方法开始的任何指针?
虽然这是对架构的看法,但我将其分解为:
数据层 - 此层负责在执行的应用程序之外(通常)访问资源。这包括;数据库,文件IO,Web Api等
业务/逻辑层 - 此层的职责(可以进一步细分)应该验证,授权,验证和构建代表业务需求的对象。要构建这些对象,它可能会使用一个或多个数据访问对象(例如,它可能使用IO DA从本地文件系统或Azure存储中检索映像,并使用数据库DA检索有关该映像的元数据)。
Presentation / Exposure-Tier - 该层的职责是将对象包装并转换为消费者需求(winforms,wpf,html,json,xml,二进制序列化等)。
通过将逻辑排除在数据层之外(即使在多租户系统中),您可以获得跨所有系统访问数据的能力(并相信我在这里需要投入大量资金)。
这可能比我在这么短的地方和我的意见中解释得多。我将要离开很多但是这里去了。
数据层
namespace ProjectsData
{
public interface IProjectDA
{
IProjectDO GetProject(Guid projectId, Guid organizationId);
}
private class ProjectDA : DbContext, IProjectDA
{
public ProjectDA (...)
public IEnumerable<ProjectDO> Projects { get; set; }
protected override void OnModelCreating(ModelBuilder builder) {... }
public IProjectDO GetProject(Guid projectId, Guid organizationId)
{
var result = Projects
.FirstOrDefault(p => p.Id == projectId && OrganizationId = organizationId);
return result;
}
}
public interface IProjectDO{ ... }
private class ProjectDO: IProjectDO
{
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
public Guid CategoryId { get; set; }
}
}
逻辑
namespace ProjectBusiness
{
public interface IProjectBO { .. }
public interface IOrganization
{
Guid OrganizationId { get; }
}
private class ProjectBA : IProjectBO
{
private readonly IProjectDA _projectDA;
private readonly IIdentity _identity;
private readonly IOrganization _organization;
public ProjectLogic(IProjectDA projectDA,
IIdentity identity,
IOrganizationContext organizationContext)
{
_projectDA = projectDA;
_identity = identity;
}
public IProjectBO GetProject(Guid id)
{
var do = _projectDA
.GetProject(id, _organization);
var result = map.To<ProjectBO>(do);
return result;
}
}
public interface IProjectBO { .. }
private class ProjectBO
{
public Guid Id { get; set; }
public Guid OrganizationId { get; set; }
public Guid CategoryId { get; set; }
}
}
因此,在这些情况下,数据层知道请求的类型,但不是多租户意识。它不是基于任何东西限制所有请求。该架构在许多方面都是有利的。
首先,在上面的示例中,您的产品起飞,您的主管想知道哪些类别最受欢迎。
namespace StatisticsBusiness
{
public interface IStatisticsBO
{
IEnumerable<ICategoryStatisticBO> CategoryStatistics { get; set; }
}
public interface ICategoryStaticBO
{
Guid CategoryId { get; }
int ProjectCount { get; }
}
private class StatisticsBA : IStatisticsBO
{
private readonly IProjectDA _projectDA;
private readonly IIdentity _identity;
public ProjectLogic(IProjectDA projectDA,
IIdentity identity)
{
_projectDA = projectDA;
_identity = identity;
}
public IEnumerable<IProjectBO GetOrderedCategoryPopularity()
{
var dos = _projectDA
.GetProjectCategoryCounts()
var result = map.To<IEnumerable<IStatisticsBO>>(dos);
return result;
}
}
public interface IStatisticsBO{ .. }
private class StatisticsBO
{
public Guid CategoryId { get; }
public int ProjectCount { get; }
}
}
注意:有些人喜欢将表达式作为谓词传递。两者都有其优点和缺点。如果您决定使用谓词路由,则必须确定所有数据访问类型是否都使用谓词。只是意识到使用针对IO或Web Api的谓词可能会更加努力,值得。
其次,某些要求会导致您无法使用实体框架。您可以用Dapper或其他一些新的更好的技术/框架替换它。所有你必须创建新的I<whataver>DA
类,因为消费逻辑不知道除了那些接口之外的任何东西(programming against an interface,L in SOLID programming principles和I in SOLID programming principles)。
我并不是一直使用这种模式,因为对于一些较小的网站来说,它的收益太多了。
我建议将解决方案分为两部分
- 在dbcontext中添加组织ID,非常类似于多租户环境中的租户ID。例如,请参阅此link。
- 下一个挑战是将组织ID作为参数传递给DbContext构造函数。为此,您可以为DbContext创建工厂。由于您将OrganizationId存储在声明中。工厂可以访问相同的声明HttpContext并将组织ID作为参数传递,同时立即执行dbContext。
这不是完美的,但可以给你一个起点。
以上是关于DbContext模型构建器中的用户详细信息的主要内容,如果未能解决你的问题,请参考以下文章
javascript 在移动构建器中删除页面bg图像(页面bg不是为了在不重新生成移动设备的情况下更新而构建的)。详细信息:https://instapage.atlassian。
javascript 在移动构建器中删除页面bg图像(页面bg不是为了在不重新生成移动设备的情况下更新而构建的)。详细信息:https://instapage.atlassian。
如何使用 Net Core 在 DbContext 中获取用户信息