【问题标题】:How to create roles in ASP.NET Core and assign them to users?如何在 ASP.NET Core 中创建角色并将其分配给用户?
【发布时间】:2017-07-17 05:55:24
【问题描述】:

我正在使用 ASP.NET Core 默认网站模板并将身份验证选为“个人用户帐户”。如何创建角色并将其分配给用户,以便我可以使用控制器中的角色来过滤访问?

【问题讨论】:

  • 你知道在登录时识别用户角色吗?

标签: c# asp.net asp.net-mvc asp.net-core asp.net-identity-3


【解决方案1】:

我的评论已被删除,因为我提供了指向我回答的类似问题的链接here。所以,这次我会更详细地回答它。来了。

您可以通过在 startup 类中创建 CreateRoles 方法轻松地做到这一点。这有助于检查是否创建了角色,如果没有创建角色;在应用程序启动时。像这样。

private async Task CreateRoles(IServiceProvider serviceProvider)
    {
        //initializing custom roles 
        var RoleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        var UserManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        string[] roleNames = { "Admin", "Manager", "Member" };
        IdentityResult roleResult;

        foreach (var roleName in roleNames)
        {
            var roleExist = await RoleManager.RoleExistsAsync(roleName);
            if (!roleExist)
            {
                //create the roles and seed them to the database: Question 1
                roleResult = await RoleManager.CreateAsync(new IdentityRole(roleName));
            }
        }

        //Here you could create a super user who will maintain the web app
        var poweruser = new ApplicationUser
        {

            UserName = Configuration["AppSettings:UserName"],
            Email = Configuration["AppSettings:UserEmail"],
        };
    //Ensure you have these values in your appsettings.json file
        string userPWD = Configuration["AppSettings:UserPassword"];
        var _user = await UserManager.FindByEmailAsync(Configuration["AppSettings:AdminUserEmail"]);

       if(_user == null)
       {
            var createPowerUser = await UserManager.CreateAsync(poweruser, userPWD);
            if (createPowerUser.Succeeded)
            {
                //here we tie the new user to the role
                await UserManager.AddToRoleAsync(poweruser, "Admin");

            }
       }
    }

然后您可以从 Startup 类中的Configure 方法调用CreateRoles(serviceProvider).Wait(); 方法。 确保在 Configure 类中有 IServiceProvider 作为参数。

在控制器中使用基于角色的授权来过滤用户访问:问题 2

你可以很容易地做到这一点,就像这样。

[Authorize(Roles="Manager")]
public class ManageController : Controller
{
   //....
}

你也可以像这样在 action 方法中使用基于角色的授权。分配多个角色,如果你愿意的话

[Authorize(Roles="Admin, Manager")]
public IActionResult Index()
{
/*
 .....
 */ 
}

虽然这很好用,但为了更好地实践,您可能需要阅读有关使用基于策略的角色检查的信息。你可以在 ASP.NET 核心文档here 上找到它,或者我写的这篇文章here

【讨论】:

  • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
  • 谢谢琼。我在答案中包含了代码的基本部分,并按照建议提供了参考链接。
  • 现在看起来不错了。 +1(因为你现在不值得 -1)
  • 在新的 ApplicationUser 部分,添加 EmailConfirmed = true 会更好吗?
  • @mahmoudfathy 将services.AddDefaultIdentity&lt;ApplicationUser&gt;().AddRoles&lt;IdentityRole&gt;().AddEntityFrameworkStores&lt;DbContext&gt;(); 添加到您的ConfigureServices
【解决方案2】:

我在Accounts 控制器中创建了一个操作,该操作调用一个函数来创建角色并将Admin 角色分配给默认用户。 (您可能应该删除生产中的默认用户):

    private async Task CreateRolesandUsers()
    {  
        bool x = await _roleManager.RoleExistsAsync("Admin");
        if (!x)
        {
            // first we create Admin rool    
            var role = new IdentityRole();
            role.Name = "Admin";
            await _roleManager.CreateAsync(role);

            //Here we create a Admin super user who will maintain the website                   

            var user = new ApplicationUser();
            user.UserName = "default";
            user.Email = "default@default.com";

            string userPWD = "somepassword";

            IdentityResult chkUser = await _userManager.CreateAsync(user, userPWD);

            //Add default User to Role Admin    
            if (chkUser.Succeeded)
            {
                var result1 = await _userManager.AddToRoleAsync(user, "Admin");
            }
        }

        // creating Creating Manager role     
        x = await _roleManager.RoleExistsAsync("Manager");
        if (!x)
        {
            var role = new IdentityRole();
            role.Name = "Manager";
            await _roleManager.CreateAsync(role);
        }

        // creating Creating Employee role     
        x = await _roleManager.RoleExistsAsync("Employee");
        if (!x)
        {
            var role = new IdentityRole();
            role.Name = "Employee";
            await _roleManager.CreateAsync(role);
        }
  }

之后您可以创建一个控制器来管理用户的角色。

【讨论】:

  • 如何获取所有具有角色的用户的列表,我想撤销角色并编辑相关角色我该怎么做?
  • @BipnPaul 为此,您可以使用用户管理器:_userManager.GetUsersInRoleAsync("admin");
  • 这很好,但是如何在注册期间将这些角色分配给用户并在登录期间识别用户角色?请帮助我陷入困境?
  • 我开始了一个完整的 js 编程工作,所以我用 asp.net 进行了旧的测试。但是当你创建一个新用户时,你应该用新用户调用“addToRoleAsync”。要控制用户的权限,您应该使用如下所述的方法 [Authorize("admin")]。
  • _roleManager 是什么类型?
【解决方案3】:

Temi 的回答几乎是正确的,但您不能像他建议的那样从非异步函数调用异步函数。您需要做的是在同步函数中进行异步调用,如下所示:

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IServiceProvider serviceProvider)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseIdentity();

        // Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

        CreateRoles(serviceProvider);

    }

    private void CreateRoles(IServiceProvider serviceProvider)
    {

        var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();
        Task<IdentityResult> roleResult;
        string email = "someone@somewhere.com";

        //Check that there is an Administrator role and create if not
        Task<bool> hasAdminRole = roleManager.RoleExistsAsync("Administrator");
        hasAdminRole.Wait();

        if (!hasAdminRole.Result)
        {
            roleResult = roleManager.CreateAsync(new IdentityRole("Administrator"));
            roleResult.Wait();
        }

        //Check if the admin user exists and create it if not
        //Add to the Administrator role

        Task<ApplicationUser> testUser = userManager.FindByEmailAsync(email);
        testUser.Wait();

        if (testUser.Result == null)
        {
            ApplicationUser administrator = new ApplicationUser();
            administrator.Email = email;
            administrator.UserName = email;

            Task<IdentityResult> newUser = userManager.CreateAsync(administrator, "_AStrongP@ssword!");
            newUser.Wait();

            if (newUser.Result.Succeeded)
            {
                Task<IdentityResult> newUserRole = userManager.AddToRoleAsync(administrator, "Administrator");
                newUserRole.Wait();
            }
        }

    }

关键是使用Task类并强制系统以稍微不同的方式同步等待。

【讨论】:

  • 我认为您的回答与问题无关。
  • 其实我认为这是最好的答案之一,但是,我不会使用那些 UGLY Task hasAdminRole = roleManager.RoleExistsAsync("Administrator");并改用 var adminRoleExist = roleManager.RoleExistsAsync("Administrator").Result;另外我不喜欢电子邮件是硬编码的,将第二部分移到注册控制器,如果不存在管理员,则用户会自动添加到管理员角色...
  • 为什么不把它放在Main可以异步的程序中,我们使用Roles配置作为IWebHost扩展。这似乎是由一些 Microsofties 建议的(扩展,而不是主要的异步):docs.microsoft.com/en-us/archive/msdn-magazine/2019/april/…
【解决方案4】:

我用这个(DI):

public class IdentitySeed
{
    private readonly ApplicationDbContext _context;
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly RoleManager<ApplicationRole> _rolesManager;
    private readonly ILogger _logger;

    public IdentitySeed(
        ApplicationDbContext context,
        UserManager<ApplicationUser> userManager,
        RoleManager<ApplicationRole> roleManager,
         ILoggerFactory loggerFactory) {
        _context = context;
        _userManager = userManager;
        _rolesManager = roleManager;
        _logger = loggerFactory.CreateLogger<IdentitySeed>();
    }

    public async Task CreateRoles() {
        if (await _context.Roles.AnyAsync()) {// not waste time
            _logger.LogInformation("Exists Roles.");
            return;
        }
        var adminRole = "Admin";
        var roleNames = new String[] { adminRole, "Manager", "Crew", "Guest", "Designer" };

        foreach (var roleName in roleNames) {
            var role = await _rolesManager.RoleExistsAsync(roleName);
            if (!role) {
                var result = await _rolesManager.CreateAsync(new ApplicationRole { Name = roleName });
                //
                _logger.LogInformation("Create {0}: {1}", roleName, result.Succeeded);
            }
        }
        // administrator
        var user = new ApplicationUser {
            UserName = "Administrator",
            Email = "something@something.com",
            EmailConfirmed = true
        };
        var i = await _userManager.FindByEmailAsync(user.Email);
        if (i == null) {
            var adminUser = await _userManager.CreateAsync(user, "Something*");
            if (adminUser.Succeeded) {
                await _userManager.AddToRoleAsync(user, adminRole);
                //
                _logger.LogInformation("Create {0}", user.UserName);
            }
        }
    }
    //! By: Luis Harvey Triana Vega
}

【讨论】:

【解决方案5】:

以下代码适用于 ISA。

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, 
        IServiceProvider serviceProvider)
    {
        loggerFactory.AddConsole(Configuration.GetSection("Logging"));
        loggerFactory.AddDebug();

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
            app.UseDatabaseErrorPage();
            app.UseBrowserLink();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseIdentity();

        // Add external authentication middleware below. To configure them please see https://go.microsoft.com/fwlink/?LinkID=532715

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });

        CreateRolesAndAdminUser(serviceProvider);
    }

    private static void CreateRolesAndAdminUser(IServiceProvider serviceProvider)
    {
        const string adminRoleName = "Administrator";
        string[] roleNames = { adminRoleName, "Manager", "Member" };

        foreach (string roleName in roleNames)
        {
            CreateRole(serviceProvider, roleName);
        }

        // Get these value from "appsettings.json" file.
        string adminUserEmail = "someone22@somewhere.com";
        string adminPwd = "_AStrongP1@ssword!";
        AddUserToRole(serviceProvider, adminUserEmail, adminPwd, adminRoleName);
    }

    /// <summary>
    /// Create a role if not exists.
    /// </summary>
    /// <param name="serviceProvider">Service Provider</param>
    /// <param name="roleName">Role Name</param>
    private static void CreateRole(IServiceProvider serviceProvider, string roleName)
    {
        var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();

        Task<bool> roleExists = roleManager.RoleExistsAsync(roleName);
        roleExists.Wait();

        if (!roleExists.Result)
        {
            Task<IdentityResult> roleResult = roleManager.CreateAsync(new IdentityRole(roleName));
            roleResult.Wait();
        }
    }

    /// <summary>
    /// Add user to a role if the user exists, otherwise, create the user and adds him to the role.
    /// </summary>
    /// <param name="serviceProvider">Service Provider</param>
    /// <param name="userEmail">User Email</param>
    /// <param name="userPwd">User Password. Used to create the user if not exists.</param>
    /// <param name="roleName">Role Name</param>
    private static void AddUserToRole(IServiceProvider serviceProvider, string userEmail, 
        string userPwd, string roleName)
    {
        var userManager = serviceProvider.GetRequiredService<UserManager<ApplicationUser>>();

        Task<ApplicationUser> checkAppUser = userManager.FindByEmailAsync(userEmail);
        checkAppUser.Wait();

        ApplicationUser appUser = checkAppUser.Result;

        if (checkAppUser.Result == null)
        {
            ApplicationUser newAppUser = new ApplicationUser
            {
                Email = userEmail,
                UserName = userEmail
            };

            Task<IdentityResult> taskCreateAppUser = userManager.CreateAsync(newAppUser, userPwd);
            taskCreateAppUser.Wait();

            if (taskCreateAppUser.Result.Succeeded)
            {
                appUser = newAppUser;
            }
        }

        Task<IdentityResult> newUserRole = userManager.AddToRoleAsync(appUser, roleName);
        newUserRole.Wait();
    }

【讨论】:

    【解决方案6】:

    在 Configure 方法中声明您的角色管理器(启动)

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env, RoleManager<IdentityRole> roleManager)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
    
            app.UseHttpsRedirection();
    
            app.UseRouting();
    
            app.UseAuthorization();
    
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
    
            Task.Run(()=>this.CreateRoles(roleManager)).Wait();
        }
    
    
        private async Task CreateRoles(RoleManager<IdentityRole> roleManager)
        {
            foreach (string rol in this.Configuration.GetSection("Roles").Get<List<string>>())
            {
                if (!await roleManager.RoleExistsAsync(rol))
                {
                    await roleManager.CreateAsync(new IdentityRole(rol));
                }
            }
        }
    

    可选 - 在 appsettings.JSON 中(取决于你想从哪里获取角色)

    {
    "Roles": [
    "SuperAdmin",
    "Admin",
    "Employee",
    "Customer"
      ]
    }
    

    【讨论】:

      【解决方案7】:

      除了 Temi Lajumoke 的回答,值得注意的是,在在 ASP.NET Core 2.1 MVC Web 应用程序中创建所需角色并将其分配给特定用户后,启动应用程序后,您可能会遇到方法错误,例如注册或管理帐户:

      InvalidOperationException:无法解析服务类型 'Microsoft.AspNetCore.Identity.UI.Services.IEmailSender' 而 试图激活 'WebApplication.Areas.Identity.Pages.Account.Manage.IndexModel'。

      可以通过添加 AddDefaultUI() 方法在 ConfigureServices 方法中快速纠正类似错误:

      services.AddIdentity<IdentityUser, IdentityRole>()
      //services.AddDefaultIdentity<IdentityUser>()
          .AddEntityFrameworkStores<ApplicationDbContext>()
          .AddDefaultUI()
          .AddDefaultTokenProviders();
      

      检查

       https://blogs.msdn.microsoft.com/webdev/2018/03/02/aspnetcore-2-1-identity-ui/

      以及 github 上的相关主题:

       https://github.com/aspnet/Docs/issues/6784 了解更多信息。

      对于为特定用户分配角色,可以使用 IdentityUser 类而不是 ApplicationUser。

      【讨论】:

        【解决方案8】:

        2020 年更新。如果您愿意,可以使用另一种方式。

         IdentityResult res = new IdentityResult();
         var _role = new IdentityRole();
         _role.Name = role.RoleName;
          res = await _roleManager.CreateAsync(_role);
          if (!res.Succeeded)
          {
                foreach (IdentityError er in res.Errors)
                {
                     ModelState.AddModelError(string.Empty, er.Description);
                 }
                 ViewBag.UserMessage = "Error Adding Role";
                 return View();
          }
          else
          {
                ViewBag.UserMessage = "Role Added";
                return View();
           }
        

        【讨论】:

          猜你喜欢
          • 2019-09-23
          • 1970-01-01
          • 2015-08-01
          • 2013-01-02
          • 2021-05-01
          • 2014-03-11
          • 1970-01-01
          • 2017-08-30
          • 1970-01-01
          相关资源
          最近更新 更多