简体   繁体   English

如何有条件地将 map 多个模型添加到 ASP.NET 核心标识中的一张表(AspNetUsers)?

[英]How to conditionally map multiple models to one table (AspNetUsers) in ASP.NET Core Identity?

I'm creating a learning assessment web application in ASP.NET Core MVC.我正在 ASP.NET Core MVC 中创建学习评估 web 应用程序。 I plan to have two separate databases: one for the users using Identity Framework and another for my data using Dapper.我计划拥有两个独立的数据库:一个用于使用 Identity Framework 的用户,另一个用于使用 Dapper 的数据。 However, I have models having relationships with my users( Instructor , Student ).但是,我的模型与我的用户( InstructorStudent )有关系。 Here is the Entity-Relationship diagram I drew showing the relations:这是我绘制的显示关系的实体关系图:

实体关系图 For instance, I have to include a Course navigation property for each Student instance.例如,我必须为每个Student实例包含一个Course导航属性。 Likewise, TestInstance contains navigation properties for both Instructor and Student , making a clear distinction between the two user classes.同样, TestInstance包含InstructorStudent的导航属性,明确区分了两个用户类。 I also need another user class called Administrator :我还需要另一个名为Administrator的用户 class :

User Class用户 Class Responsibilities责任
Student Attends tests参加考试
Instructor Creates and schedules tests创建和安排测试
Administrator Manages instructor and student accounts and courses.管理教师和学生的帐户和课程。 Has all the privileges of an instructor拥有导师的所有特权

I know custom properties can be created in Identity by deriving from IdentityUser but I need to maintain three different user classes and Identity provides just one table called AspNetUsers .我知道可以通过从IdentityUser派生来在 Identity 中创建自定义属性,但我需要维护三个不同的用户类,而 Identity 只提供一个名为AspNetUsers的表。 I don't want to directly use tables from Identity in my domain model.我不想在我的域 model 中直接使用 Identity 中的表。 In fact, it would be great if Identity can have its own separate database.事实上,如果 Identity 可以拥有自己的独立数据库,那就太好了。 The administrator will be the one who would create and manage instructor and student accounts.管理员将是创建和管理教师和学生帐户的人。

My question is:我的问题是:

Is there any way that I can create three models/entities Student , Instructor and Adminstrator as part of my domain model and then have them all use the IDs in the Identity's AspNetUsers table?有什么方法可以创建三个模型/实体StudentInstructorAdminstrator作为我的域 model 的一部分,然后让它们都使用 Identity 的AspNetUsers表中的 ID? Their role information can be stored as a claim or in the AspNetUserRoles table provided by Identity.他们的角色信息可以存储为声明或 Identity 提供的AspNetUserRoles表中。

I can then use Identity to add policies to implement access control.然后我可以使用 Identity 添加策略来实现访问控制。

I hope it is not a design flaw.我希望这不是设计缺陷。 I can still reconsider the design if so as my project is in the initial stage.如果我的项目处于初始阶段,我仍然可以重新考虑设计。

You can use TPT With EF Core 5 for example, this project Integrates TPT with ASP.NET Core Identity.例如,您可以将 TPT 与 EF Core 5 一起使用,此项目将 TPT 与 ASP.NET Core Identity 集成。

https://github.com/ArminShoeibi/SchoolManagementSystem https://github.com/ArminShoeibi/SchoolManagementSystem

 public class ApplicationUser : IdentityUser<Guid>
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string NationalCode { get; set; }
        public DateTime BirthDate { get; set; }
        public Gender Gender { get; set; }

    }

 public class Student : ApplicationUser
    {
        public string FatherName { get; set; }
        public string PlaceOfBirth { get; set; }
        public string Address { get; set; }
        public string HomePhoneNumber { get; set; }
    }

 public class Teacher : ApplicationUser
    {
        public string FieldOfStudy { get; set; }
        public AcademicDegree AcademicDegree{ get; set; }
        public int YearsOfExperience { get; set; }
    }


  public class SchoolMgmtContext : IdentityDbContext<ApplicationUser,ApplicationRole,Guid>
    {


        public SchoolMgmtContext(DbContextOptions<SchoolMgmtContext> dbContextOptions)
            :base(dbContextOptions)
        {

        }

        public DbSet<Teacher> Teachers { get; set; }
        public DbSet<Student> Students { get; set; }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            base.OnModelCreating(builder);
            builder.Entity<ApplicationUser>().ToTable("Users");
            builder.Entity<ApplicationRole>().ToTable("Roles");

            builder.Entity<Student>().ToTable("Students");
            builder.Entity<Teacher>().ToTable("Teachers");
         

        }
    }

and the result is:结果是: 在此处输入图像描述

Can an instructor also be an administrator?讲师也可以是管理员吗? How could such multi-role authorizations be handled?如何处理这种多角色授权?

Perhaps this is not relevant in this case, but I like to think about such quality/architectural concerns before I get confronted with a change request from the users afterwards due to "new insights".也许这在这种情况下无关紧要,但我喜欢在随后因“新见解”而面临用户的更改请求之前考虑此类质量/架构问题。

Personally, I would consider creating a kind of Role table, containing the three roles.就个人而言,我会考虑创建一种Role表,其中包含三个角色。 Using a separate UserRole table, you could create a many-to-many relation between the users and their role(s).使用单独的UserRole表,您可以在用户及其角色之间创建多对多关系。 So instead of using inheritance/derivation, I would use a kind of composition here.因此,我将在这里使用一种组合,而不是使用继承/派生。

I think your current logic using the AspNetUsers will remain intact.我认为您当前使用AspNetUsers的逻辑将保持不变。 Perhaps you can use Identity to add policies to implement access control based on these two additional role-related tables?也许您可以使用 Identity 添加策略,以基于这两个额外的角色相关表来实现访问控制?

EDIT编辑

You could also go a step further and create an additional Right table, containing the separate user rights, like attending tests, creating tests, scheduling tests, managing accounts, etc. You could create a separate RoleRight table to assign those rights to the desired roles.您还可以进一步 go 并创建一个附加的Right表,其中包含单独的用户权限,例如参加测试、创建测试、安排测试、管理帐户等。您可以创建一个单独的RoleRight表以将这些权限分配给所需的角色.

This would make your roles more dymamic and perhaps even configurable by users.这将使您的角色更具动态性,甚至可能由用户配置。 (In the latter case only if the user has rights to create and manage roles, of course.) (当然,在后一种情况下,只有用户有权创建和管理角色。)

And in your code, you could then check if the user has specific rights assigned (by its roles).然后在您的代码中,您可以检查用户是否具有分配的特定权限(通过其角色)。 For example, in the code that is responsible for creating tests, you might actually want to check if the user has the right to create tests instead of explicitly checking if the user is an instructor.例如,在负责创建测试的代码中,您可能实际上想要检查用户是否有权创建测试,而不是明确检查用户是否是讲师。

Anyway, that's just my 50 cents to this issue.无论如何,这只是我对这个问题的 50 美分。 Hope it helps.希望能帮助到你。

I think that you can solve this problem quite easily by creating a users table that is a manifest of all the system users that might access the system (students, instructors, admins) containing shared properties such as Ids, names, email adresses, etc. (be sure to salt any passwords you store!)我认为您可以通过创建一个用户表来轻松解决这个问题,该表是所有可能访问系统的系统用户(学生、教师、管理员)的清单,其中包含 ID、名称、email 地址等共享属性。 (一定要加盐你存储的任何密码!)

Then you have two options for moving forward: you can go with the multi-table approach you have here, and just have each 'role table' be a join to the users table via userId and store unique properties to that role: In you example, a student table would probably be just a course Id and a User Id.然后,您有两个前进的选择:您可以使用此处的多表方法 go ,只需让每个“角色表”通过 userId 连接到用户表并将唯一属性存储到该角色:在您的示例中,学生表可能只是一个课程 ID 和一个用户 ID。 This lets you customize each role with additional properties as you discover them.这使您可以在发现每个角色时使用其他属性自定义它们。

Alternately, you could combine the roles into a single table, but unless you do some work to abstract unique properties, you will probably end up with a really wide table that contains a lot of blank values for properties that don't apply to every role.或者,您可以将角色组合到一个表中,但除非您做一些工作来抽象独特的属性,否则您最终可能会得到一个非常宽的表,其中包含许多不适用于每个角色的属性的空白值. Don't do this.不要这样做。 Its easy at first, but as your app grows, this table will turn into a hot mess.一开始很容易,但是随着你的应用程序的增长,这个表会变得一团糟。

Just adding a 'users' table should allow you to forge forward with minimal changes to your existing schema.只需添加一个“用户”表,您就可以通过对现有架构的最小更改来进行改进。

One other note: You have a 1:1 relationship between students and courses.另一个注意事项:学生和课程之间是一对一的关系。 I could be wrong, but you probably want this to be a one to many, since most students will take multiple courses at a time.我可能是错的,但您可能希望这是一对多的,因为大多数学生一次会学习多门课程。 Your mileage may vary.你的旅费可能会改变。

Because of the tight integration因为紧密结合

I would like to suggest that the existence of a tight integration is the core issue.我想提出紧密集成的存在是核心问题。 If your design does not create a tight integration, then the problem disappears.如果您的设计没有创建紧密集成,那么问题就会消失。 You determine how tightly integrated your design is.您可以确定您的设计的集成程度。

Separation Of Concerns关注点分离

There are good arguments and real-world use cases for maintaining a separate database for Identity and one for the application itself.有很好的 arguments 和实际用例,用于为身份维护一个单独的数据库,为应用程序本身维护一个数据库。 I recently developed and deployed such an application and I am very happy with the results.我最近开发和部署了这样一个应用程序,我对结果非常满意。

The first reason being "What happens when another application is added to the mix?".一个原因是“当另一个应用程序添加到组合中时会发生什么?”。 Out in the wild, identity services tend to be isolated: Azure AD, Google Cloud Identity, AWS Identity and Access Management, etc. Aside from the inherent security benefits, an Identity Service will support all of your applications, present and future, and should not be tightly coupled within one specific application.在野外,身份服务往往是孤立的:Azure AD、Google Cloud Identity、AWS 身份和访问管理等。除了固有的安全优势,身份服务将支持您现在和未来的所有应用程序,并且应该在一个特定的应用程序中不紧密耦合。

Your application is web-based: what happens when users demand a mobile application?您的应用程序是基于 Web 的:当用户需要移动应用程序时会发生什么? If Identity is only accessible through the web application, what now?如果身份只能通过 web 应用程序访问,那么现在该怎么办? The web app probably uses session-based authentication, so you will need to rewrite all of that in order to support mobile applications. web 应用程序可能使用基于会话的身份验证,因此您需要重写所有这些以支持移动应用程序。 It won't be pretty.不会很漂亮

On the other hand, let's say you had separated the services.另一方面,假设您已经分离了服务。 Furthermore, because your design called for the Identity service to be platform-agnostic, you implemented JWT (JSON Web Tokens) support for authentication.此外,由于您的设计要求身份服务与平台无关,因此您实现了 JWT(JSON Web 令牌)支持身份验证。 In this scenario, authentication for the mobile application will work exactly the same , with no changes在这种情况下,移动应用程序的身份验证将完全相同,没有任何变化

Let's take this scenario one step further: users of your application are tired of hitting "refresh" to see if their test scores are available (pull).让我们把这个场景更进一步:你的应用程序的用户已经厌倦了点击“刷新”来查看他们的测试分数是否可用(拉)。 They are demanding to be notified when test scores are ready (push).他们要求在考试成绩准备好(推送)时得到通知

The implementation of mobile push notifications has nothing to do with the core functionality of the application;移动推送通知的实现与应用的核心功能无关 it is a user/platform-centric feature.它是以用户/平台为中心的功能。 If you are not convinced this is true, consider 2FA (Two Factor Authentication) utilizing a mobile device as the second factor.如果您不相信这是真的,请考虑使用移动设备作为第二个因素的 2FA(双因素身份验证)。

Identity is never a good place to experiment, and arguably the last place you want to make a mistake.身份从来都不是一个试验的好地方,而且可以说是你最不想犯错误的地方。 I believe everything you add or tweak in an Identity solution can potentially increase the attack vector.我相信您在身份解决方案中添加或调整的所有内容都可能增加攻击向量。 This is the textbook example of KISS (Keep It Simple Stupid).这是 KISS (Keep It Simple Stupid) 的教科书示例。

Connecting a User to Identity将用户连接到身份

User table refers to the Student and Teacher tables; User表是指StudentTeacher表; Identity table refers to AspNetUsers . Identity表是指AspNetUsers

As you stated, had the tables been in a single database they would be connected using the standard "out-of-the-box" foreign key reference that we all know and love.正如您所说,如果表位于单个数据库中,它们将使用我们都知道和喜爱的标准“开箱即用”外键引用进行连接。

Here's the fun part: we get to roll our own: Fundamentally a foreign key is very basic concept, here's an id.这是有趣的部分:我们可以自己动手:从根本上说,外键是非常基本的概念,这是一个 id。 use it to reference something.用它来引用一些东西。 That is the only requirement for this implementation of a foreign key reference.这是外键引用实现的唯一要求。

Keep in mind: a User is not the same as an Identity .请记住: UserIdentity不同。 It is common for systems to contain data for User s who will never log into their systems.系统通常会包含永远不会登录其系统的User的数据。 Also, a site administrator will most likely not be a Teacher or Student .此外,站点管理员很可能不是TeacherStudent

For the standard use-case, my suggestion is to create the User entity first, followed by the Identity .对于标准用例,我的建议是首先创建User实体,然后是Identity Then update the optional column in the User table with the id of the Identity you just created.然后使用您刚刚创建的Identity的 ID 更新User表中的可选列。

You want to add a role or UserType claim (Instructor, Student) for each Identity so you know which of the User tables you will find the User .您想为每个Identity添加角色或UserType声明(Instructor、Student),以便知道您将在哪些User表中找到User

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否将用户设置存储在ASP.NET Core身份AspNetUsers表中 - Store User Settings in ASP.NET Core Identity AspNetUsers Table or Not ASP.NET 核心 AspNetUsers 上的身份 - Identity on ASP.NET Core AspNetUsers Asp.net核心 - 没有这样的表:AspNetUsers - Asp.net core - no such table: AspNetUsers dbo.AspNetUsers 表上的 ASP.NET MVC 5 核心标识 CompanyID 外键 - ASP.NET MVC 5 Core Identity CompanyID foreign key on dbo.AspNetUsers table ASP.NET Identity 从 AspNetUsers 表中删除列 - ASP.NET Identity remove column from AspNetUsers table ASP.NET MVC-将Identity与现有的经过修改的AspNetUsers表一起使用 - ASP.NET MVC - Using Identity with existing, modified AspNetUsers table 我想为 ASP.NET 核心标识中的用户创建一个帐户,但我无法将数据插入表 dbo.AspNetUsers - I want to create an account for a user in ASP.NET Core identity but I can't insert the data into table dbo.AspNetUsers 在一个 razor 视图中创建多个模型(ASP.NET Core) - Multiple create models in one razor view (ASP.NET Core) 如何获取ASP.Net MVC 5中AspNetUsers表中的ApplicationUser数量? - How to get the Number of ApplicationUser in the AspNetUsers Table in ASP.Net MVC 5? 如何在asp.net core中添加多个身份和多个角色 - How to add multiple identity and multiple role in asp.net core
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM