简体   繁体   English

Asp.Net Core 从 ApplicationUser 派生的不同用户模型

[英]Asp.Net Core Different User Models to derive from ApplicationUser

We have just started learning how to code and we are working on an Asp.Net Core 3.1 project i know its a simple problem but ive searched everywhere and haven't found a solution.我们刚刚开始学习如何编码,我们正在研究一个 Asp.Net Core 3.1 项目,我知道这是一个简单的问题,但我到处搜索并没有找到解决方案。

We have Admin, Client, Mentor User Models which have all the additional props we need from the user apart from the standard Email, Pass, First, Last name which come from the ApplicationUser model.我们有 Admin、Client、Mentor 用户模型,除了来自 ApplicationUser 模型的标准 Email、Pass、First、Last name 之外,它们还有我们需要的所有附加道具。

so we have something like this (you can find bellow the models):所以我们有这样的东西(你可以在模型下面找到):

AdminUserDetails   ---\
ClientUserDetails  ------ : ApplicationUser : IdentityUser
MentorUserDetails  ---/

At this moment, Authentication and Authorization works correctly but all users are created in AspNetUser Table in EF but we want each role (eg.Client) to be created in the Client table with all properties from ApplicationUser and IdentityUser, inherited.此时,身份验证和授权工作正常,但所有用户都在 EF 的 AspNetUser 表中创建,但我们希望在客户端表中创建每个角色(例如客户端),并继承 ApplicationUser 和 IdentityUser 的所有属性。

First of all, i found this link to inherit the models from ApplicationUser.首先,我发现这个链接从 ApplicationUser 继承模型。 Is this the proper way to do it?这是正确的方法吗?

Also, when a user registers with a role selected in the form we want to assign that user to the corresponding ...UserDetails model and get the Identity Id in Guid.此外,当用户使用表单中选择的角色注册时,我们希望将该用户分配给相应的 ...UserDetails 模型并在 Guid 中获取身份 ID。

Here are some exmple models:以下是一些示例模型:

public class ApplicationUser : IdentityUser
    {
        [Required]
        [MaxLength(50)]
        public string FirstName { get; set; }

        [Required]
        [MaxLength(50)]
        public string LastName { get; set; }

        [NotMapped]
        public string Name
        {
            get
            {
                return FirstName + " " + LastName;
            }
        }

        [Required]
        [Display(Name = "Phone Number")]
        [DataType(DataType.PhoneNumber)]
        public int? PhoneNumber { get; set; }

        [Display(Name = "Profile Picture")]
        [DataType(DataType.Upload)]
        public string? ProfilePicture { get; set; }
   }
public class AdministratorDetails : ApplicationUser
    {
        [Key]
        [ForeignKey("ApplicationUser")]
        public Guid Id { get; set; }

        //Προσθέτω Foreign key se ola ta details APP USER

        public virtual ApplicationUser ApplicationUser { get; set; }

    }

Startup:启动:

public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddCors();
            services.AddDbContext<ApplicationDbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("DefaultConnection")));


            services.AddDefaultIdentity<ApplicationUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddRoles<IdentityRole>() //Πρόσθεσα Identity role
                .AddRoleManager<RoleManager<IdentityRole>>()
                .AddEntityFrameworkStores<ApplicationDbContext>();

            services.AddIdentityServer()
                .AddApiAuthorization<ApplicationUser, ApplicationDbContext>();

            services.AddAuthentication(options =>
                {
                    options.DefaultAuthenticateScheme = IdentityConstants.ApplicationScheme;
                    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
                    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
                })
                .AddIdentityServerJwt();


            services.AddControllersWithViews();
            services.AddRazorPages();

            // In production, the React files will be served from this directory
            services.AddSpaStaticFiles(configuration =>
            {
                configuration.RootPath = "ClientApp/build";
            });

            //SendGrid Confirmation Email Sender
            services.AddTransient<IEmailSender, EmailSender>();
            services.Configure<AuthMessageSenderOptions>(Configuration);

            services.AddTransient<IProfileService, IdentityClaimsProfileService>();
            services.AddScoped<IJobCategoriesRepository, JobCategoryRepository>();
            services.AddScoped<IMentorRepository, MentorRepository>();
            services.AddScoped<IHrDetailsRepository, HrDetailsRepository>();
            services.AddScoped<IClientRepository, ClientRepository>();
            services.AddScoped<IJobListingsRepository, JobListingsRepository>();
            services.AddScoped<IMentorOfferRepository, MentorOfferRepository>();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IServiceProvider serviceProvider)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseDatabaseErrorPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }


            app.UseCors(
                options => options.WithOrigins("https://localhost:5001/")
                                  .AllowAnyHeader()
                                  .AllowAnyMethod()
            );

            app.UseHttpsRedirection();
            app.UseStaticFiles();
            app.UseSpaStaticFiles();

            app.UseRouting();

            app.UseIdentityServer();
            app.UseAuthentication();
            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller}/{action=Index}/{id?}");
                endpoints.MapRazorPages();
            });

            app.UseSpa(spa =>
            {
                spa.Options.SourcePath = "ClientApp";

                if (env.IsDevelopment())
                {
                    spa.UseReactDevelopmentServer(npmScript: "start");
                }
            });


            app.UseStaticFiles();

            app.UseIdentityServer();

            CreateRoles(serviceProvider).Wait();
        }


        private async Task CreateRoles(IServiceProvider serviceProvider)
        {
            //adding custom roles
            var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
            var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
            string[] roleNames = { "Admin", "HR", "Mentor", "Client" };
            IdentityResult roleResult;

            foreach (var roleName in roleNames)
            {
                //creating the roles and seeding them to the database
                var roleExist = await RoleManager.RoleExistsAsync(roleName);
                if (!roleExist)
                {
                    roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
                }
            }


            //creating a super user who could maintain the web app

            var powerUser = new ApplicationUser
            {
                UserName = Configuration.GetSection("UserSettings")["UserEmail"],
                Email = Configuration.GetSection("UserSettings")["UserEmail"],

                FirstName = "PowerAdmin",
                LastName = "Admin",
                UserRole = "Admin",
                EmailConfirmed = true
            };


            string UserPassword = Configuration.GetSection("UserSettings")["UserPassword"];
            var _user = await UserManager.FindByEmailAsync(Configuration.GetSection("UserSettings")["UserEmail"]);

            if (_user == null)
            {
                var createPowerUser = await UserManager.CreateAsync(powerUser, UserPassword);
                if (createPowerUser.Succeeded)
                {
                    //here we tie the new user to the "Admin" role 
                    await UserManager.AddToRoleAsync(powerUser, "Admin");

                }

            }

        }

        public class IdentityClaimsProfileService : IProfileService
        {
            private readonly IUserClaimsPrincipalFactory<ApplicationUser> _claimsFactory;
            private readonly UserManager<ApplicationUser> _userManager;

            public IdentityClaimsProfileService(UserManager<ApplicationUser> userManager, IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory)
            {
                _userManager = userManager;
                _claimsFactory = claimsFactory;
            }

            public async Task GetProfileDataAsync(ProfileDataRequestContext context)
            {
                var sub = context.Subject.GetSubjectId();
                var user = await _userManager.FindByIdAsync(sub);
                var principal = await _claimsFactory.CreateAsync(user);
                var roles = await _userManager.GetRolesAsync(user);
                var claims = principal.Claims.ToList();
                claims = claims.Where(claim => context.RequestedClaimTypes.Contains(claim.Type)).ToList();
                foreach(string role in roles)
                {
                    claims.Add(new Claim(JwtClaimTypes.Role, role));
                }

                context.IssuedClaims = claims;
            }

            public async Task IsActiveAsync(IsActiveContext context)
            {
                var sub = context.Subject.GetSubjectId();
                var user = await _userManager.FindByIdAsync(sub);
                context.IsActive = user != null;
            }
        }

Thanks to @Xin Zou at the comments i finally realized that i had to remove the IdentityUser inheritance from my Users models and only set the foreign key at each User感谢@Xin Zou 在评论中我终于意识到我必须从我的用户模型中删除 IdentityUser 继承,并且只在每个用户上设置外键

 [ForeignKey("ApplicationUserId")]
 public ApplicationUser ApplicationUser { get; set; }
 public string ApplicationUserId { get; set; }

Thus creating an AspNetUser table but also a User table (according to it's role) with the foreign key of the AspNetUser.因此,创建与AspNetUser的外键的AspNetUser表,但(根据它的角色)的用户表。 The only issue here is that the User tables have to have their props nullable.这里唯一的问题是 User 表必须让它们的 props 可以为空。

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

相关问题 在ASP.NET Core MVC中注入ApplicationUser - Inject ApplicationUser in ASP.NET Core MVC 在Asp.net MVC中,视图模型是否可以从域模型派生? - In Asp.net MVC, is it advisable for viewmodels to derive from domain models? ASP.NET身份-ApplicationUser和我的自定义模型/实体 - ASP.NET Identity - ApplicationUser and my custom models / entities 如何从 ASP.net 内核 6 中的视图访问自定义 ApplicationUser 属性? - How to access custom ApplicationUser properties from view in ASP.net core 6? ASP.NET Core Identity不会注入UserManager <ApplicationUser> - ASP.NET Core Identity does not inject UserManager<ApplicationUser> 如何在 ASP.NET 内核中包含 object 的 ApplicationUser - How to include the ApplicationUser of an object in ASP.NET Core 我应该如何从ASP.NET核心视图访问我的ApplicationUser属性? - How should I access my ApplicationUser properties from ASP.NET Core Views? ASP.NET 核心 - 参数 1:无法从 'long' 转换为 '.Identity.ApplicationUser' - ASP.NET Core - Argument 1: cannot convert from 'long' to '.Identity.ApplicationUser' ApplicationUser上的ASP.net Core 1.0映射属性返回null - ASP.net Core 1.0 Mapping property on ApplicationUser returning null ApplicationUser 始终为空 ASP.NET CORE 3.0 标识 - ApplicationUser always null ASP.NET CORE 3.0 Identity
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM