【问题标题】:How do I seed user roles in Identity ASP.NET Core 2.1 (Identity Scaffolded)如何在 Identity ASP.NET Core 2.1(Identity Scaffolded)中播种用户角色
【发布时间】:2018-10-08 18:52:40
【问题描述】:

当身份被搭建时,我如何为“管理员”用户角色播种?

我想通过电子邮件查找我的超级用户帐户并设置管理员角色。 我发现大多数示例使用Startup.cs,但您应该使用IdentityHostingStartup.cs 注册身份相关服务。

那么我在哪里/如何在IdentityHostingStartup 中注入RoleManagerUserManager? (我认为这是我需要的,如果有更好的方法请告诉我)

  public class IdentityHostingStartup : IHostingStartup
  {
        public void Configure(IWebHostBuilder builder)
        {
            builder.ConfigureServices((context, services) => {
                services.AddDbContext<MyWebContext>(options =>
                    options.UseSqlServer(
                        context.Configuration.GetConnectionString("MyWebContextConnection")));

                services.AddIdentity<MyWebUser, MyWebRole>()
                    .AddRoles<MyWebRole>()
                    .AddRoleManager<RoleManager<MyWebRole>>()
                    .AddDefaultUI()
                    .AddEntityFrameworkStores<MyWebContext>();

                services.Configure<IdentityOptions>(options => {
                    options.Password.RequireNonAlphanumeric = false;
                    });
            });
        }
  }

【问题讨论】:

    标签: c# asp.net-core asp.net-identity


    【解决方案1】:

    您无法在 Web 主机 builder 上执行数据播种,因为那时还没有构建服务提供者。相反,您必须先实际创建虚拟主机,然后才能解析您之前注册的任何服务。

    我通常的建议是在创建WebHost 之后在Program.cs 中执行初始播种。按照默认模板,我会将Main 方法调整为如下所示:

    public static async Task Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();
    
        using (var scope = host.Services.CreateScope())
        {
            var roleManager = scope.ServiceProvider.GetService<RoleManager<MyWebRole>>();
    
            if (!await roleManager.RoleExistsAsync("admin"))
                await roleManager.CreateAsync(new MyWebRole { Name = "admin" });
        }
    
        await host.RunAsync();
    }
    

    所以这将首先创建 web 主机,然后它将创建一个依赖注入范围,它将从中解析一个 RoleManager 实例。然后,您可以使用该经理创建您需要的角色。

    您也可以为此创建一个单独的服务,因此您不需要在 Program.cs 中包含所有这些逻辑,而只需依赖其他一些服务来执行数据播种:

    public static async Task Main(string[] args)
    {
        var host = CreateWebHostBuilder(args).Build();
    
        using (var scope = host.Services.CreateScope())
        {
            var dataSeeder = scope.ServiceProvider.GetService<DataSeeder>();
            await dataSeeder.EnsureSeedDataAsync();
        }
    
        await host.RunAsync();
    }
    

    DataSeeder 然后将注册到依赖注入容器中。然后它可以将RoleManager 和其他服务(例如选项,甚至数据库上下文)作为依赖项,并在EnsureSeedDataAsync 方法中执行播种。

    另一种方法是使用Entity Framework Core data seeding functionality,在模型构建器上调用.HasData() 方法。但是,这需要您的角色对象具有固定 ID,并且您还必须在数据库级别创建对象,而不是依赖更高级别的 RoleManager

    【讨论】:

    • 在使用 .HasData() 时迁移发生了什么有点令人困惑。首先,我在那里添加了 asp.net 身份的角色,但没有明确提供 Id。这导致为每次迁移重新生成角色。然后我提供了 ID,这仍然会导致 migrationbuilder 在每次后续迁移中更新角色。
    • 如果数据库还没有创建,我有一个异常。我该如何解决?如果我注释行 2await dataSeeder.EnsureSeedDataAsync();",启动应用程序,停止应用程序,取消注释该行并重新开始,它工作完美
    • @Orion 您可以使用dbContext.Database.EnsureCreatedAsync()dbContext.Database.MigrateAsync()(使用迁移时)来确保您的数据库存在(或迁移到最新版本)。
    【解决方案2】:

    有点旧的线程,但这可能会帮助任何寻求它的人。您可以在 IdentityDbContext.cs 文件中的 OnModelCreating() 方法中为用户和角色播种,如下所示。请注意,应预定义密钥以避免在每次执行此方法时播种新用户和新角色:

    protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
    
            //Seeding a  'Administrator' role to AspNetRoles table
            modelBuilder.Entity<IdentityRole>().HasData(new IdentityRole {Id = "2c5e174e-3b0e-446f-86af-483d56fd7210", Name = "Administrator", NormalizedName = "ADMINISTRATOR".ToUpper() });
    
    
            //a hasher to hash the password before seeding the user to the db
            var hasher = new PasswordHasher<IdentityUser>();
    
    
            //Seeding the User to AspNetUsers table
            modelBuilder.Entity<IdentityUser>().HasData(
                new IdentityUser
                {
                    Id = "8e445865-a24d-4543-a6c6-9443d048cdb9", // primary key
                    UserName = "myuser",
                    NormalizedUserName = "MYUSER",
                    PasswordHash = hasher.HashPassword(null, "Pa$$w0rd")
                }
            );
    
    
            //Seeding the relation between our user and role to AspNetUserRoles table
            modelBuilder.Entity<IdentityUserRole<string>>().HasData(
                new IdentityUserRole<string>
                {
                    RoleId = "2c5e174e-3b0e-446f-86af-483d56fd7210", 
                    UserId = "8e445865-a24d-4543-a6c6-9443d048cdb9"
                }
            );
            
    
        }
    

    【讨论】:

      猜你喜欢
      • 2018-01-08
      • 2019-05-28
      • 2016-03-24
      • 2015-01-09
      • 2017-06-25
      • 2022-11-23
      • 2013-12-26
      • 2019-01-31
      • 2018-12-27
      相关资源
      最近更新 更多