Asp.net core ASP.NET Core 2.2创建标识用户

Asp.net core ASP.NET Core 2.2创建标识用户,asp.net-core,identity,seeding,asp.net-core-identity,usermanager,Asp.net Core,Identity,Seeding,Asp.net Core Identity,Usermanager,ASP.Net核心是全新的。必须创建具有标识的asp.net core 2.2项目(并为用户设定种子) 我找不到任何关于如何做到这一点的文档 我能够找到创建身份角色的代码(不管怎样编译,我还没有找到可以运行它的地方: private static async Task CreateUserTypes(ApplicationDbContext authContext, IServiceProvider serviceProvider) { var RoleManager = se

ASP.Net核心是全新的。必须创建具有标识的asp.net core 2.2项目(并为用户设定种子)

我找不到任何关于如何做到这一点的文档

我能够找到创建身份角色的代码(不管怎样编译,我还没有找到可以运行它的地方:

  private static async Task CreateUserTypes(ApplicationDbContext authContext, IServiceProvider serviceProvider)
  {
     var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
     string[] roleNames = { "Administrator", "Data Manager", "Interviewer", "Respondent" };
     IdentityResult roleResult;
     foreach (var roleName in roleNames)
     {
        var roleExist = await RoleManager.RoleExistsAsync(roleName);
        if (!roleExist)
        {
           roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
        }
     }
  }
我们将研究CreateUserManager的其他参数是什么,以及如何从serviceProvider获取这些参数

--欧文

找到了解决方法。关键是找到正确的服务提供商来传递和创建用户管理器的正确语法。我通过谷歌找到的其他答案都是用他们自己的
应用程序用户来替换
标识用户
,这让事情变得一团糟。下面是我的工作ng功能(希望这对某人有帮助):

private静态异步任务CreateRootUser(Models.CensORContext上下文、ApplicationDbContext authContext、IServiceProvider服务提供者)
{
//为all things ADMIN创建根管理员用户。
var userStore=新的userStore(authContext);
UserManager UserManager=serviceProvider.GetRequiredService();
//新的用户管理器(userStore,null,null,null,null,null,null,serviceProvider,null);
//=serviceProvider.GetRequiredService();
IdentityUser用户=新IdentityUser()
{
用户名=”admin@admin.admin",
电子邮件=”admin@admin.admin"
};
var result=await userManager.CreateAsync(用户,“密码”);
结果=wait userManager.AddToRoleAsync(用户,“管理员”);
}

您的主要问题似乎是依赖项注入。有关详细信息,请查看。只要您以正确的方式注入
DbContext
UserManager
,其余的代码就可以了

下面是一个例子。您可以为种子设定单独的服务,以确保您的代码与其他代码分离

public class UserSeeder
{
    private readonly UserManager<IdentityUser> userManager;
    private readonly ApplicationDbContext context;

    public UserSeeder(UserManager<IdentityUser> userManager, ApplicationDbContext context)
    {
        this.userManager = userManager;
        this.context = context;
    }

    public async Task `()
    {
        string username = "admin@admin.admin";
        var users = context.Users;
        if (!context.Users.Any(u => u.UserName == username))
        {
            var done = await userManager.CreateAsync(new IdentityUser
            {
                UserName = username,
                Email = username
            }, username);
        }
    }

}

请注意,这两种方法都是每次调用数据库。您可以计划将其放置在何处。您还可以确保在布尔值的帮助下(可以是单例)只调用一次。但请注意,这只会在应用程序启动时运行。

以下是我为管理用户设定种子的方法(从《EF核心行动》一书中学习):

这是
用户
类:

public class User : IdentityUser<long>
{
    //add your extra properties and relations
}
public class Role : IdentityRole<long>
{
    public static string Admin = "Admin";
}
它可以是空的,我使用静态字符串来避免代码中的魔法字符串

这是
DbContext

public class ApplicationDbContext : IdentityDbContext<User, Role, long>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    { }

    //your DbSets and configurations
    //...
}
这是种子数据的扩展方法:

public static class SeedData
{
    public static IWebHost SeedAdminUser(this IWebHost webHost)
    {
        using (var scope = webHost.Services.CreateScope())
        {
            try
            {
                var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                context.Database.EnsureCreated();

                var userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
                var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<Role>>();

                if (!userManager.Users.Any(u => u.Email == "admin@domain.com"))
                {
                    roleManager.CreateAsync(new Role()
                    {
                        Name = Role.Admin
                    })
                    .Wait();

                    userManager.CreateAsync(new User
                    {
                        UserName = "Admin",
                        Email = "admin@domain.com"
                    }, "secret")
                    .Wait();

                    userManager.AddToRoleAsync(userManager.FindByEmailAsync("admin@domain.com").Result, Role.Admin).Wait();
                }                    
            }
            catch (Exception ex)
            {
                var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred while seeding user.");
                //throw;
            }
        }

        return webHost;
    }
}

我理解在试图让代码正常工作时的挫折感,尤其是在时间紧迫的情况下。我也理解大声喊出来的诱惑。我们都有过这样或那样的经历。虽然您的问题确实传达了您的编码问题是什么,但在发布问题时请尽量保持冷静。这样,所有人都会更加关注您的编程问题。您是否使用个人用户的默认模板创建了新项目?我建议您添加最后一段,似乎是工作代码,作为您的答案,并将其从中删除问题看一看。这似乎是你真正的问题所在,而不是身份。这将有助于更好地理解这个概念。stackOverflow不会让我发布答案(没有足够的声誉点数)-因此,我在答案中加入了我的工作代码。我相信还有更好的方法可以做到这一点…谢谢大家的评论和帮助。我将努力降低我的沮丧情绪-当周围没有人时,很容易大声喊叫…谢谢。这是一个很好的方法,信息量很大,但是有两个建议。首先,不要使用
GetRequiredService
对于每个服务,如果您创建一个单独的类并将其用作服务,它将更干净、更灵活。其次,您可以在startup中的
Configure
函数上运行它,而不是创建扩展并在program.cs上运行(代码更像是startup的工作)。我还发现前三组代码实际上与问题不相关。
Configure
方法中的代码将针对每个请求运行。种子数据在应用程序启动期间只应出现一次。不完全如此。
Configure
方法仅调用一次。函数中创建的中间件将针对每个请求调用一次请求。我说的是调用configure内部的
SeedAdminUser
,而不是创建中间件。我如何“在主控制器中注入UserSeeder”?-或者-我应该将“app.Use(..”放在哪里因此,我有一个上下文,等等。要注入控制器或任何服务,您需要将其作为构造函数参数
public home controller(UserSeeder UserSeeder)
传递。基本上,与我将
UserManager
注入控制器中的
UserSeeder
的方式相同。
app.Use(
Startup
类中的
Confugure
函数的开头。啊……这个注入功能非常强大,我已经习惯了不同的语法。你有没有推荐一个blog/blog/course/等来了解如何使用它(不一定是它如何工作或如何构建它)?
public class User : IdentityUser<long>
{
    //add your extra properties and relations
}
public class Role : IdentityRole<long>
{
    public static string Admin = "Admin";
}
public class ApplicationDbContext : IdentityDbContext<User, Role, long>
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
        : base(options)
    { }

    //your DbSets and configurations
    //...
}
public void ConfigureServices(IServiceCollection services)
{
    //...

    services.AddIdentity<User, Role>(options =>
        {
            //you can configure your password and user policy here
            //for example:
            options.Password.RequireDigit = false;
        })
        .AddEntityFrameworkStores<ApplicationDbContext>()
        .AddDefaultTokenProviders();

    //...
}
public static class SeedData
{
    public static IWebHost SeedAdminUser(this IWebHost webHost)
    {
        using (var scope = webHost.Services.CreateScope())
        {
            try
            {
                var context = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
                context.Database.EnsureCreated();

                var userManager = scope.ServiceProvider.GetRequiredService<UserManager<User>>();
                var roleManager = scope.ServiceProvider.GetRequiredService<RoleManager<Role>>();

                if (!userManager.Users.Any(u => u.Email == "admin@domain.com"))
                {
                    roleManager.CreateAsync(new Role()
                    {
                        Name = Role.Admin
                    })
                    .Wait();

                    userManager.CreateAsync(new User
                    {
                        UserName = "Admin",
                        Email = "admin@domain.com"
                    }, "secret")
                    .Wait();

                    userManager.AddToRoleAsync(userManager.FindByEmailAsync("admin@domain.com").Result, Role.Admin).Wait();
                }                    
            }
            catch (Exception ex)
            {
                var logger = scope.ServiceProvider.GetRequiredService<ILogger<Program>>();
                logger.LogError(ex, "An error occurred while seeding user.");
                //throw;
            }
        }

        return webHost;
    }
}
CreateWebHostBuilder(args)
    .Build()
    .SeedAdminUser()
    .Run();