web-dev-qa-db-ja.com

ASP.NET Core Identityアプリケーションの起動時にカスタムユーザーロールを追加

ASP.NET Coreアプリケーションでは、さまざまなユーザー権限を管理するための基礎として特定の役割を作成したいと思います。悲しいことに、ドキュメントにはカスタムロールの使用方法が詳細に説明されています。コントローラー/アクションではなく、それらを作成する方法ではありません。これにRoleManager<IdentityRole>を使用できることを発見しました。この場合、定義されたASP.NET Core IDがアプリケーションに登録されると、インスタンスがコントローラーコンストラクターに自動的に挿入されます。

これにより、次のようなカスタムロールを追加できます。

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

動作し、データベースにロールを作成します。ただし、このチェックは常に特定のコントローラー/アクションを呼び出すデータベースのオーバーヘッドを作成します。そのため、カスタムロールが存在する場合は、アプリケーションの起動後にonceを確認して追加します。 Startup.csのConfigureServicesメソッドはこれに適しているようです。

しかし、これを行うためにRoleManager<IdentityRole>クラスのインスタンスを作成するにはどうすればよいですか? ASP.NET Coreが使用しているため、ここではベストプラクティスアプローチを使用し、依存インスタンスを自分で作成することで混乱しないようにします。このようなものに対する依存性注入(これも私の意見では合理的です)。

言い換えれば、私は依存性注入を使用する必要があります外部コントローラーの。

19
Lion

起動時にデータベースを移行およびシードするニーズの例を次に示します。

静的クラスを作成します。

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();
}
25
tmg

データベースに既にロールが挿入されていない場合にのみ、データをシードすることをお勧めします。他のWordでは、アプリケーションが初めて実行されるときにのみロールを保存します。

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

        }
    }
}

そしてStartup.csで:

public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    ...

    RolesData.SeedRoles(app.ApplicationServices).Wait();
}
6
Millan Sanchez