ASP.NET Core 2.2 Создать IdentityUser - PullRequest
       94

ASP.NET Core 2.2 Создать IdentityUser

0 голосов
/ 08 декабря 2018

Совершенно новый для ASP.Net Core.Необходимость создания проекта ядра 2.2 для asp.net с идентификацией (и просеивания пользователей).

Я не могу найти никакой документации о том, как это сделать точно.

Мне удалось найтикод для создания Identity Roles (все равно компилируется, еще не дошел до того места, где я могу его запустить:

  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));
        }
     }
  }

Теперь мне нужно создать несколько пользователей. Но для этого нужен странный синтаксис MicrosoftЯ не могу найти (гуглил 2 дня).

Вот что работает не :

   private static async Task CreateRootUser(Models.CensORContext context, ApplicationDbContext authContext, IServiceProvider serviceProvider)
  {
     //Create the root ADMIN user for all things admin.
     UserManager<ApplicationDbContext> userManager = serviceProvider.GetRequiredService<UserManager<ApplicationDbContext>>();

     IdentityUser user = new IdentityUser()
     {
        UserName = "admin@admin.admin",
        Email = "admin@admin.admin"
     };

     var NewAdmin = await userManager.CreateAsync(user, "password");
  }

Я вижу ошибку:

Аргумент 1: невозможно преобразовать из «Microsoft.AspNetCore.Identity.IdentityUser» в «ApplicationDbContext»

Означает ли это? Очевидно, у меня нет нужного userManager. Но, как мне получить правильный , который принимает пользователя в качестве 1-го параметра и строку (пароль) для 2-го?

Кроме того, примеры, которые появляются в поисках Google, имеют ApplicationUser объект, которого у меня нет (и не нужен?). Не определено вдостаточно о том, как я получаю это.

Оуэн

ОК.Получил синтаксическую ошибку, но теперь я получаю ошибку времени выполнения:

NullReferenceException: Ссылка на объект не установлена ​​на экземпляр объекта.по вызову CreateAsync.Вот новый код:

private static async Task CreateRootUser(Models.CensORContext context, ApplicationDbContext authContext, IServiceProvider serviceProvider)
{
     //Create the root ADMIN user for all things admin.         
     var userStore = new UserStore<IdentityUser>(authContext);
     UserManager<IdentityUser> userManager = new UserManager<IdentityUser>(userStore, null, null, null, null, null, null, serviceProvider, null);
     // = serviceProvider.GetRequiredService<UserManager<ApplicationDbContext>>();

     IdentityUser user = new IdentityUser()
     {
        UserName = "admin@admin.admin",
        Email = "admin@admin.admin"
     };

     var result = await userManager.CreateAsync(user, "password");
}

Собираемся узнать, какие другие параметры есть для создания userManager и как их получить из serviceProvider?

- Оуэн

Разобрался, как это сделать.Ключ находил правильный сервис-провайдер для передачи и правильного синтаксиса для создания userManager.Другие ответы, которые я нашел через Google все , заменили IdentityUser их собственными ApplicationUser, которые мутили воду.Вот рабочая функция (надеюсь, это кому-нибудь поможет):

  private static async Task CreateRootUser(Models.CensORContext context, ApplicationDbContext authContext, IServiceProvider serviceProvider)
  {
     //Create the root ADMIN user for all things admin.         
     var userStore = new UserStore<IdentityUser>(authContext);
     UserManager<IdentityUser> userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();
     //new UserManager<IdentityUser>(userStore, null, null, null, null, null, null, serviceProvider, null);
     // = serviceProvider.GetRequiredService<UserManager<ApplicationDbContext>>();

     IdentityUser user = new IdentityUser()
     {
        UserName = "admin@admin.admin",
        Email = "admin@admin.admin"
     };

     var result = await userManager.CreateAsync(user, "password");
     result = await userManager.AddToRoleAsync(user, "Administrator");
  }

Ответы [ 2 ]

0 голосов
/ 09 декабря 2018

Вот как я заполняю моего администратора (учится у EF Core в действии книга):

Это класс User:

public class User : IdentityUser<long>
{
    //add your extra properties and relations
}

long тип указывает тип первичного ключа.Если вы используете класс IdentityUser по умолчанию, это будет строка (uniqueidentifier в SQL).

Это класс Role:

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
    //...
}

Если вы собираетесь использовать Identity, вам нужно использовать IdentityDbContext и указатьваш пользовательский класс User и Role и тип используемого вами первичного ключа.

Этот код добавляет идентификацию в программу:

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;
    }
}

И, наконец, используйте их в своем Program.cs:

CreateWebHostBuilder(args)
    .Build()
    .SeedAdminUser()
    .Run();
0 голосов
/ 09 декабря 2018

Кажется, ваша главная проблема - внедрение зависимостей.Посмотрите эту ссылку для получения дополнительной информации.Пока вы вводите свои 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);
        }
    }

}

Затем вам нужно добавить этот класс в качестве области (так как ваша область DbContext определена), используя services.AddScoped<UserSeeder>() при запуске.Теперь вы можете просто ввести свой UserSeeder в любом сервисе (кроме синглетонов) и вызвать функцию UserSeeder.Например, вы можете ввести UserSeeder в домашний контроллер и назвать его индексным действием.Таким образом, посев проверяется и добавляется изначально.Тем не менее, это будет работать, только если вы перейдете на главную страницу в первую очередь.Кроме того, вы можете настроить промежуточное программное обеспечение в своем классе запуска следующим образом:

app.Use(async (context, next) => {
    await context.RequestServices.GetService<UserSeeder>().SeedAsync();
    await next();
});

Обратите внимание, что в обоих случаях вы вызываете базу данных каждый раз.Вы можете планировать, где его разместить.Вы также можете убедиться, что это вызывается только один раз с помощью логического значения (может быть в синглтоне).Но обратите внимание, что это будет работать только при запуске приложения.

...