ASP.NET核心2.2创建IdentityUser
ASP.NET Core 2.2 Create IdentityUser
ASP.Net Core 的全新内容。必须使用 Identity 创建 asp.net 核心 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));
}
}
}
现在,我需要创建一些用户。但是我找不到用奇怪的微软语法来做的事情(谷歌搜索了 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");
}
我看到的错误是:
Argument1: cannot convert from 'Microsoft.AspNetCore.Identity.IdentityUser' to 'ApplicationDbContext'
是什么意思?显然,我没有合适的 userManager。但是,如何获得正确的 将用户作为第一个参数,将字符串(密码)作为第二个参数?
此外,Google 搜索中出现的示例有一个 ApplicationUser
对象,我没有(也不需要? ).示例中未定义我如何获得它。
欧文
好的。过去有语法错误,但现在我遇到 运行 时间错误:
NullReferenceException: Object reference not set to an instance of an object. on the call to CreateAsync. Here's the new code:
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");
}
您的主要问题似乎是依赖注入。查看 this link 了解更多信息。只要您以正确的方式注入 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);
}
}
}
然后您必须在启动时使用 services.AddScoped<UserSeeder>()
将此 class 添加为作用域(因为您的 DbContext
是作用域)。您现在可以简单地将您的 UserSeeder
注入任何服务(单例除外)并调用您的 UserSeeder
函数。例如,您可以在家庭控制器中注入 UserSeeder
并将其称为索引操作。通过这种方式,最初会检查并添加播种。但是,这只有在您先访问主页时才有效。或者,您可以在启动时设置这样的中间件 class:
app.Use(async (context, next) => {
await context.RequestServices.GetService<UserSeeder>().SeedAsync();
await next();
});
请注意,这两种方式,您每次都在调用数据库。您可以计划放置它的位置。您还可以确保在布尔值的帮助下只调用一次(可以是单例)。但请注意,这只会在应用程序启动时 运行。
这是我为管理员用户播种的方式(从 EF Core in Action 一书中学习):
这是User
class:
public class User : IdentityUser<long>
{
//add your extra properties and relations
}
long
类型指定主键类型。如果您使用默认 IdentityUser
class 它将是字符串(SQL 中的唯一标识符)。
这是Role
class:
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
class 以及您使用的主键类型正在使用。
此代码将身份添加到程序中:
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();
ASP.Net Core 的全新内容。必须使用 Identity 创建 asp.net 核心 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));
}
}
}
现在,我需要创建一些用户。但是我找不到用奇怪的微软语法来做的事情(谷歌搜索了 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");
}
我看到的错误是:
Argument1: cannot convert from 'Microsoft.AspNetCore.Identity.IdentityUser' to 'ApplicationDbContext'
是什么意思?显然,我没有合适的 userManager。但是,如何获得正确的 将用户作为第一个参数,将字符串(密码)作为第二个参数?
此外,Google 搜索中出现的示例有一个 ApplicationUser
对象,我没有(也不需要? ).示例中未定义我如何获得它。
欧文
好的。过去有语法错误,但现在我遇到 运行 时间错误:
NullReferenceException: Object reference not set to an instance of an object. on the call to CreateAsync. Here's the new code:
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");
}
您的主要问题似乎是依赖注入。查看 this link 了解更多信息。只要您以正确的方式注入 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);
}
}
}
然后您必须在启动时使用 services.AddScoped<UserSeeder>()
将此 class 添加为作用域(因为您的 DbContext
是作用域)。您现在可以简单地将您的 UserSeeder
注入任何服务(单例除外)并调用您的 UserSeeder
函数。例如,您可以在家庭控制器中注入 UserSeeder
并将其称为索引操作。通过这种方式,最初会检查并添加播种。但是,这只有在您先访问主页时才有效。或者,您可以在启动时设置这样的中间件 class:
app.Use(async (context, next) => {
await context.RequestServices.GetService<UserSeeder>().SeedAsync();
await next();
});
请注意,这两种方式,您每次都在调用数据库。您可以计划放置它的位置。您还可以确保在布尔值的帮助下只调用一次(可以是单例)。但请注意,这只会在应用程序启动时 运行。
这是我为管理员用户播种的方式(从 EF Core in Action 一书中学习):
这是User
class:
public class User : IdentityUser<long>
{
//add your extra properties and relations
}
long
类型指定主键类型。如果您使用默认 IdentityUser
class 它将是字符串(SQL 中的唯一标识符)。
这是Role
class:
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
class 以及您使用的主键类型正在使用。
此代码将身份添加到程序中:
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();