我们可以在 ASP.NET Identity 中使用硬编码角色吗?

Can we have hard-coded roles in ASP.NET Identity?

我是 ASP.NET Identity 的新手,正在为角色而苦苦挣扎。我以前在桌面应用程序中的经验(我们显然不能使用 ASP.NET 身份,主要是滚动我们自己的角色),我们通常为角色添加一个 enum。这使我们能够在代码中明确地引用它们。

ASP.NET 身份似乎需要角色存储在数据库中。我的主要问题是我们不能保证每个人(所有开发人员、测试和生产数据库)在我们的数据库中都有相同的数据。通过使用 enum,数据在代码中被硬编码,因此不会出现歧义。

次要(但仍然非常重要)的问题是角色似乎依赖于您使用硬编码字符串...

[Authorize(Roles = "SomeRole")]
public IActionResult SomeAction() =>
  View();

这看起来很脆弱。角色名称很容易打错,如果我们想更改名称怎么办?我们必须找到硬编码字符串的每个实例并进行更改。

澄清一下,角色被用来限制对网站某些区域的访问。我们将有一套固定的角色,很少会改变。如果他们确实改变了,代码也需要随之改变,所以动态访问角色(例如通过站点的 CRUD 部分)是没有意义的。

我们能做到吗?如果不是,我们如何解决知道如何引用可能不存在的角色的问题?

为避免输入错误,您可以尝试const

  1. RoleConst

    public class RoleConst
    {
        public const string Admin = "Admin";
        public const string User = "User";
    }
    
  2. 插入角色

    public class Program
    {
        public static void Main(string[] args)
        {
            //CreateWebHostBuilder(args).Build().Run();
            var host = CreateWebHostBuilder(args).Build();
            using (var scope = host.Services.CreateScope())
            {
                var services = scope.ServiceProvider;
                try
                {
                    RoleManager<IdentityRole> roleManager = services.GetRequiredService<RoleManager<IdentityRole>>();
                    if(roleManager.Roles.Count() == 0)
                    {
                        //insert role
                        roleManager.CreateAsync(new IdentityRole(RoleConst.Admin)).ConfigureAwait(true);
                        roleManager.CreateAsync(new IdentityRole(RoleConst.User)).ConfigureAwait(true);
                    }
                }
                catch (Exception ex)
                {
                    var logger = services.GetRequiredService<ILogger<Program>>();
                    logger.LogError(ex, "An error occurred while seeding the database.");
                }
            }
    
            host.Run();
        }
    
        public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
            WebHost.CreateDefaultBuilder(args)
                .UseStartup<Startup>();
    }
    
  3. 使用 AuthorizeRole

    [Authorize(Roles = RoleConst.Admin)]
    public IActionResult Privacy()
    {
        return View();
    }