ASP.NET Core 2.2创建标识用户



全新的ASP.Net Core。必须使用Identity创建一个asp.net核心2.2项目(并为用户播种(。

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

我找到了创建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));
}
}
}

现在,我需要创建一些用户。但我找不到用奇怪的微软语法做的(已经在谷歌上搜索了两天(。

以下是不能工作的内容:

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

我看到的错误是:

Argument1:无法从"Microsoft.AspNetCore.Identity.IdentityUser"转换为"ApplicationDbContext">

这意味着什么?显然,我没有合适的userManager。但是,如何获得正确的,将用户作为第一个参数,将字符串(密码(作为第二个参数?

此外,谷歌搜索中出现的示例有一个ApplicationUser对象,而我没有(也不需要?(。示例中没有定义我是如何得到它的。

Owen

好的。过去有语法错误,但现在我遇到了运行时错误:

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

将研究createuserManager的其他参数是什么,以及如何从serviceProvider获得这些参数?

--Owen

弄清楚了如何做到这一点。关键是找到正确的服务提供商来传递创建userManager的正确语法。我在谷歌上找到的其他答案都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");
}

您的主要问题似乎是依赖项注入。请查看此链接以获取更多信息。只要以正确的方式注入DbContextUserManager,代码的其余部分就可以了。

下面是一个例子。您可以为种子设置一个单独的服务,以确保您将代码与其他代码解耦。

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

然后,您必须在启动时使用services.AddScoped<UserSeeder>()将此类添加为scoped(因为您的DbContext是scoped(。现在,您可以简单地将UserSeeder注入任何服务(singleton除外(并调用UserSeeder函数。例如,您可以在家庭控制器中注入UserSeeder,并将其称为索引操作。通过这种方式,首先检查并添加种子。然而,只有当你先转到主页时,这才会起作用。或者,您可以在启动类中设置这样的中间件:

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

请注意,通过这两种方式,每次都调用数据库。你可以计划把它放在哪里。你也可以确保在布尔值的帮助下只调用一次(可以是单例(。但请注意,这只会在应用程序启动时运行。

以下是我如何为我的管理员用户种子(从EF Core in Action书中学习(:

这是User类:

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

long类型指定主键类型。如果使用默认的IdentityUser类,它将是字符串(SQL中的uniqueidentifier(。

这是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并指定自定义的UserRole类以及正在使用的主键类型。

此代码将Identity添加到程序中:

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

最新更新