授权数据创建种子

在创建授权数据种子前,先创建一个用户角色的枚举。

创建UserRole

public enum UserRole
{
    Admin,
    Teacher
}

这里定义了2个角色,分别是管理员教师

创建IdentityDataSeeder

创建一个IdentityDataSeeder类,并在类中创建Seed方法,用于生成角色和用户。

如果不存在角色,则创建枚举中的2个角色。

如果不存在用户,则分别创建1个管理员用户和教师用户。

代码如下:

public class IdentityDataSeeder(UserManager<IdentityUser> userManager, RoleManager<IdentityRole> roleManager)
{
    public async Task Seed()
    {
        if (!roleManager.Roles.Any())
        {
            await roleManager.CreateAsync(new IdentityRole(UserRole.Admin.ToString()));
            await roleManager.CreateAsync(new IdentityRole(UserRole.Teacher.ToString()));
        }

        if (!userManager.Users.Any())
        {
            IdentityUser user1 = new IdentityUser { UserName = "root" };
            await userManager.CreateAsync(user1, "123456");
            await userManager.AddToRoleAsync(user1, UserRole.Admin.ToString());

            IdentityUser user2 = new IdentityUser { UserName = "Nyazira" };
            await userManager.CreateAsync(user2, "123456");
            await userManager.AddToRoleAsync(user2, UserRole.Teacher.ToString());
        }
    }
}

在这里,我们注入了UserManager<IdentityUser>RoleManager<IdentityRole>的实例。

其中RoleManager用于创建角色,UserManager用于创建用户并给用户授权。

IdentityRoleIdentityUser分别是角色和用户的模型。

RoleManager通过CreateAsync方法创建角色。

UserManager也通过CreateAsync方法创建用户,并通过AddToRoleAsync给用户授予相应的角色。

虽然这个方法已经写完,但是却无法使用,原因是框架没办法注入UserManagerRoleManager的实例。

它们的实例需要手动添加。

添加授权服务

services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<AppDbContext>();

通过AddIdentity方法可以添加授权服务,并通过AddEntityFrameworkStores方法指定角色和用户数据存储的位置。

密码规则

我们在Seed方法中设置的密码非常简单,这样的密码是无法通过默认密码规则的。

可以通过设置修改密码规则,代码如下:

services.Configure<IdentityOptions>(options =>
{
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 3;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireLowercase = false;
    options.Password.RequireUppercase = false;
    options.Password.RequireDigit = false;
});
  • options.Password.RequiredLength = 6;
    • 密码最小长度:设置密码的最小长度为6个字符。
  • options.Password.RequiredUniqueChars = 3;
    • 密码中需要的唯一字符数:设置密码中必须包含至少3个不同的字符。
  • options.Password.RequireNonAlphanumeric = false;
    • 是否需要非字母数字字符:设置为false,表示密码中不需要包含特殊字符(如@#等)。
  • options.Password.RequireLowercase = false;
    • 是否需要小写字母:设置为false,表示密码中不需要包含小写字母。
  • options.Password.RequireUppercase = false;
    • 是否需要大写字母:设置为false,表示密码中不需要包含大写字母。
  • options.Password.RequireDigit = false;
    • 是否需要数字:设置为false,表示密码中不需要包含数字。

将IdentityDataSeeder设置为服务

services.AddTransient<IdentityDataSeeder>();

在项目启动时调用Seed方法

using (var scope = app.Services.CreateScope())
{
    var serviceProvider = scope.ServiceProvider;
    var identityDataSeeder = serviceProvider.GetRequiredService<IdentityDataSeeder>();
    identityDataSeeder.Seed().Wait();
}

最终Main方法中的代码如下:

var builder = WebApplication.CreateBuilder(args);

IServiceCollection services = builder.Services;
services.AddControllersWithViews();
services.AddDbContext<AppDbContext>();
services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<AppDbContext>

services.Configure<IdentityOptions>(options =>
{
    options.Password.RequiredLength = 6;
    options.Password.RequiredUniqueChars = 3;
    options.Password.RequireNonAlphanumeric = false;
    options.Password.RequireLowercase = false;
    options.Password.RequireUppercase = false;
    options.Password.RequireDigit = false;
});

services.AddScoped<MajorRepo>();
services.AddScoped<GradeRepo>();
services.AddScoped<ClassRepo>();
services.AddScoped<StudentRepo>();

services.AddScoped<MajorService>();
services.AddScoped<GradeService>();
services.AddScoped<ClassService>();
services.AddScoped<StudentService>();
services.AddScoped<SearchService>();

services.AddTransient<IdentityDataSeeder>();

var app = builder.Build();
using (var scope = app.Services.CreateScope())
{
    var serviceProvider = scope.ServiceProvider;
    var identityDataSeeder = serviceProvider.GetRequiredService<IdentityDataSeeder>();
    identityDataSeeder.Seed().Wait();
}

app.UseStatusCodePagesWithReExecute("/error/{0}");
app.UseStaticFiles();
app.MapDefaultControllerRoute();

app.Run();

重启项目

重启项目后,打开数据库,查看AspNetRoles和AspNetUsers两张表,会发现里面添加了2个角色和2个用户,且用户的密码已做混淆处理。