ASP.在应用程序启动时添加自定义用户角色

本文关键字:自定义 用户 角色 添加 应用程序 启动 ASP | 更新日期: 2023-09-27 18:12:20

. NET Core应用程序,我想创建一定的角色作为基础来管理不同的用户权限。遗憾的是,文档详细说明了如何在控制器/动作中使用自定义角色,但没有说明如何创建它们。我发现我可以使用RoleManager<IdentityRole>来实现这一点,其中实例被自动注入到控制器构造函数中,当它被定义和ASP。. NET核心标识在应用程序中注册。

让我添加这样一个自定义角色:

var testRole = new IdentityRole("TestRole");
if(!roleManager.RoleExistsAsync(testRole.Name).Result) {
    roleManager.CreateAsync(testRole);
}

它工作并在数据库中创建角色。但是这种检查总是会在数据库上创建开销,调用特定的控制器/操作。所以我想检查一旦在我的应用程序已经启动,如果自定义角色存在并添加它们。Startup.cs中的ConfigureServices方法似乎很适合于此。

但是:我如何创建RoleManager<IdentityRole>类的实例来做到这一点?我想在这里使用最佳实践方法,而不是通过自己创建依赖实例来搞乱,这似乎会导致大量的工作,因为它没有很好的文档,肯定不会遵循最佳实践,因为ASP。. NET Core正在使用依赖注入来做这样的事情(在我看来这也是合理的)。

换句话说:我需要在控制器的之外使用依赖注入

ASP.在应用程序启动时添加自定义用户角色

下面是一个在启动时迁移和播种数据库的示例:

创建静态类:
public static class RolesData
{
    private static readonly string[] Roles = new string[] {"Administrator", "Editor", "Subscriber"};
    public static async Task SeedRoles(IServiceProvider serviceProvider)
    {
        using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var dbContext = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
            if (dbContext.Database.GetPendingMigrations().Any())
            {
                await dbContext.Database.MigrateAsync();
                var roleManager = serviceScope.ServiceProvider.GetRequiredService<RoleManager<IdentityRole>>();
                foreach (var role in Roles)
                {
                    if (!await roleManager.RoleExistsAsync(role))
                    {
                        await roleManager.CreateAsync(new IdentityRole(role));
                    }
                }
            }
        }
    }
}

Startup.cs中:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    ...
    RolesData.SeedRoles(app.ApplicationServices).Wait();
}

我宁愿只在数据库中没有插入角色时才播种数据。换句话说,只在应用程序第一次运行时存储角色:

public static class RolesData
{
    private static readonly string[] Roles = new string[] { "Administrator", "Editor", "Subscriber" };
    public static async Task SeedRoles(IServiceProvider serviceProvider)
    {
        using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var dbContext = serviceScope.ServiceProvider.GetService<AppDbContext>();
            if (!dbContext.UserRoles.Any())
            {
                var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
                foreach (var role in Roles)
                {
                    if (!await roleManager.RoleExistsAsync(role))
                    {
                        await roleManager.CreateAsync(new IdentityRole(role));
                    }
                }
            }
        }
    }
}

And on Startup.cs:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    ...
    RolesData.SeedRoles(app.ApplicationServices).Wait();
}

以防有人来这里寻找。net 5的解决方案,这里是:

除了Configure方法中的比特之外,一切都几乎与@Millan Sanchez的答案相同…

I was getting

One or more errors occurred. (Cannot resolve scoped service 'Microsoft.AspNetCore.Identity.RoleManager`1[Microsoft.AspNetCore.Identity.IdemtityRole]' from root provider.)' 

经过一番搜索,我找到了这个StackOverflow的答案

基本上,我所需要做的就是将IServiceProvider添加到Configure方法的参数中,并将其传递给我对SeedUsers的调用,而不是app.applicationServices

完整代码:

public static class RolesData
{
    private static readonly string[] Roles = new string[] { "Administrator", "Editor", "Subscriber" };
    public static async Task SeedRoles(IServiceProvider serviceProvider)
    {
        using (var serviceScope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            var dbContext = serviceScope.ServiceProvider.GetService<AppDbContext>();
            if (!dbContext.UserRoles.Any())
            {
                var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
                foreach (var role in Roles)
                {
                    if (!await roleManager.RoleExistsAsync(role))
                    {
                        await roleManager.CreateAsync(new IdentityRole(role));
                    }
                }
            }
        }
    }
}

And on Startup.cs:

public void Configure(IApplicationBuilder app, IWebHostEnvironment env, 
IServiceProvider serviceProvider)
{
    ...
    RolesData.SeedRoles(serviceProvider).Wait();
}