简体   繁体   English

如何在 ASP.NET Core 中创建角色并将其分配给用户?

[英]How to create roles in ASP.NET Core and assign them to users?

I am using the ASP.NET Core default website template and have the authentication selected as "Individual User Accounts".我正在使用 ASP.NET 核心默认网站模板并将身份验证选择为“个人用户帐户”。 How can I create roles and assign it to users so that I can use the roles in a controller to filter access?如何创建角色并将其分配给用户,以便我可以使用 controller 中的角色来过滤访问?

My comment was deleted because I provided a link to a similar question I answered here .我的评论已被删除,因为我提供了一个指向我在此处回答的类似问题的链接。 Ergo, I'll answer it more descriptively this time.所以,这次我会更详细地回答它。 Here goes.开始。

You could do this easily by creating a CreateRoles method in your startup class.您可以通过在startup类中创建CreateRoles方法轻松完成此操作。 This helps check if the roles are created, and creates the roles if they aren't;这有助于检查角色是否已创建,如果没有,则创建角色; on application startup.在应用程序启动时。 Like so.像这样。

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

            }
       }
    }

and then you could call the CreateRoles(serviceProvider).Wait();然后你可以调用CreateRoles(serviceProvider).Wait(); method from the Configure method in the Startup class. Startup 类中的Configure方法中的方法。 ensure you have IServiceProvider as a parameter in the Configure class.确保您将IServiceProvider作为Configure类中的参数。

Using role-based authorization in a controller to filter user access: Question 2在控制器中使用基于角色的授权来过滤用户访问:问题 2

You can do this easily, like so.你可以很容易地做到这一点,就像这样。

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

You can also use role-based authorization in the action method like so.您还可以像这样在操作方法中使用基于角色的授权。 Assign multiple roles, if you will分配多个角色,如果你愿意

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

While this works fine, for a much better practice, you might want to read about using policy based role checks.虽然这工作正常,但为了获得更好的实践,您可能需要阅读有关使用基于策略的角色检查的信息。 You can find it on the ASP.NET core documentation here , or this article I wrote about it here您可以在此处的 ASP.NET 核心文档或我在此处撰写的有关它的文章中找到它

I have created an action in the Accounts controller that calls a function to create the roles and assign the Admin role to the default user.我在Accounts控制器中创建了一个操作,该操作调用一个函数来创建角色并将Admin角色分配给默认用户。 (You should probably remove the default user in production): (您可能应该删除生产中的默认用户):

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

After you could create a controller to manage roles for the users.在您可以创建一个控制器来管理用户的角色之后。

Temi's answer is nearly correct, but you cannot call an asynchronous function from a non asynchronous function like he is suggesting. Temi 的回答几乎是正确的,但是您不能像他建议的那样从非异步函数调用异步函数。 What you need to do is make asynchronous calls in a synchronous function like so :您需要做的是在同步函数中进行异步调用,如下所示:

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

    }

The key to this is the use of the Task<> class and forcing the system to wait in a slightly different way in a synchronous way.关键是使用 Task<> 类并强制系统以稍微不同的方式以同步方式等待。

I use this (DI):我用这个(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
}

The following code will work ISA.以下代码将适用于 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();
    }

In addition to Temi Lajumoke's answer, it's worth noting that after creating the required roles and assigning them to specific users in ASP.NET Core 2.1 MVC Web Application , after launching the application, you may encounter a method error, such as registering or managing an account:除了 Temi Lajumoke 的回答,值得注意的是,在 ASP.NET Core 2.1 MVC Web Application 中创建所需角色并将其分配给特定用户后,启动应用程序后,您可能会遇到方法错误,例如注册或管理帐户:

InvalidOperationException: Unable to resolve service for type 'Microsoft.AspNetCore.Identity.UI.Services.IEmailSender' while attempting to activate 'WebApplication.Areas.Identity.Pages.Account.Manage.IndexModel'. InvalidOperationException:尝试激活“WebApplication.Areas.Identity.Pages.Account.Manage.IndexModel”时无法解析“Microsoft.AspNetCore.Identity.UI.Services.IEmailSender”类型的服务。

A similar error can be quickly corrected in the ConfigureServices method by adding the AddDefaultUI() method:通过添加 AddDefaultUI() 方法,可以在 ConfigureServices 方法中快速纠正类似的错误:

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

Check查看

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

and related topic on github:和github上的相关主题:

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

And for assigning role to specific user could be used IdentityUser class instead of ApplicationUser.并且可以使用 IdentityUser 类而不是 ApplicationUser 为特定用户分配角色。

In Configure method declare your role manager (Startup)在 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));
            }
        }
    }

OPTIONAL - In appsettings.JSON (it depends on you where you wanna get roles from)可选 - 在 appsettings.JSON 中(这取决于你想从哪里获取角色)

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

Update in 2020. Here is another way if you prefer. 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();
   }

.net 6 option: .net 6 选项:

public static class WebApplicationExtensions
{
    public static async Task<WebApplication> CreateRolesAsync(this WebApplication app, IConfiguration configuration)
    {
        using var scope = app.Services.CreateScope();
        var roleManager = (RoleManager<IdentityRole>)scope.ServiceProvider.GetService(typeof(RoleManager<IdentityRole>));
        var roles = configuration.GetSection("Roles").Get<List<string>>();

        foreach (var role in roles)
        {
            if (!await roleManager.RoleExistsAsync(role))
                await roleManager.CreateAsync(new IdentityRole(role));
        }

        return app;
    }
}

In Program.cs add before app.Run()在 Program.cs 之前添加 app.Run()

await app.CreateRolesAsync(builder.Configuration);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何在ASP.NET Core 2.2中创建角色并将其分配给用户 - How to create roles in ASP.NET Core 2.2 and assign them to users 如何使用ASP.NET Core 2.1中的网站界面为用户分配角色 - How to assign roles to users using the website interface in ASP.NET Core 2.1 如何显示具有角色的用户列表 - ASP.NET(核心) - How to display a list of users with Roles - ASP.NET (Core) 从Windows应用程序管理asp.net网站(创建新用户,将用户分配给角色等) - Administer asp.net website (create new users, assign users to roles, etc.) from a windows app 如何一次创建多个角色? (asp.net 核心) - How to create many roles at once? (asp.net core) 如何分配用户角色并向不在角色中的用户隐藏按钮,asp.net - How to assign user roles and hide buttons from users who are not in a role, asp.net 用户角色使用ASP.NET Core Identity 3的权限 - Users Roles Permissions using ASP.NET Core Identity 3 ASP.NET Core 1.1获取所有用户及其角色 - ASP.NET Core 1.1 getting all users and their roles 如何在 Asp.Net Core 3.1 上创建两种类型的用户 - How to create two types of users on Asp.Net Core 3.1 如何将用户添加到 razor 页面 asp.net 核心中创建的角色 - How to add users to created roles in razor pages asp.net core
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM