Як створити ролі в ядрі asp.net і призначити їх користувачам


76

Я використовую шаблон основного веб-сайту за замовчуванням asp.net та аутентифікацію, вибрану як індивідуальний обліковий запис користувача. Як я можу створити роль і призначити її користувачеві, щоб я міг використовувати роль у контролері для фільтрації доступу.


чи знаєте ви, щоб ідентифікувати ролі користувачів під час входу?
Yirga

Відповіді:


62

Я створив дію в контролері облікового запису, яка викликає функцію для створення ролей і впливає на роль адміністратора для користувача за замовчуванням (Вам, мабуть, слід видалити користувача за замовчуванням у виробництві):

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

Після ви можете створити контролер для управління ролями для користувачів.


Як я можу отримати список усіх користувачів, які мають ролі, я хочу відкликати ролі та відредагувати пов'язані ролі, як я можу це зробити?
Bipn Paul

1
@BipnPaul Для цього ви можете використовувати менеджер користувачів:_userManager.GetUsersInRoleAsync("admin");
Стефан Дутерієс

це чудово, але як призначити ці ролі користувачам під час реєстрації та визначити роль користувачів під час входу? будь ласка, допоможіть застрягти на цьому?
Yirga

1
Я розпочав повноцінне програмування роботи з js, тому поставив тест на asp.net на старому. Але коли ви створюєте нового користувача, вам слід викликати "addToRoleAsync" з новим користувачем. Для керування правом користувача слід використовувати метод, як описано нижче [Авторизувати ("адміністратор")].
Stephane Duteriez

4
що це за тип _roleManager?
IEnjoyEatingVegetables

92

Мій коментар було видалено, оскільки я надав посилання на подібне запитання, на яке я відповів тут . Ерго, цього разу я відповім на нього більш описово. Ось іде.

Це можна зробити легко, створивши CreateRolesметод у своєму startupкласі. Це допомагає перевірити, чи створені ролі, і створює ролі, якщо їх немає; при запуску програми. Подобається так.

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

            }
       }
    }

а потім ви можете викликати CreateRoles(serviceProvider).Wait();метод із Configureметоду в класі запуску. переконайтеся, що у вас є IServiceProviderпараметр у Configureкласі.

Використання рольової авторизації в контролері для фільтрування доступу користувачів: Питання 2

Ви можете зробити це легко, ось так.

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

Ви також можете використовувати авторизацію на основі ролей у методі дії приблизно так. Призначте кілька ролей, якщо хочете

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

Хоча це працює добре, для набагато кращої практики ви можете прочитати про використання перевірок ролей на основі політик. Ви можете знайти його в основній документації ASP.NET тут або в цій статті, про яку я писав про це тут


2
Хоча це посилання може відповісти на питання, краще включити сюди основні частини відповіді та надати посилання для довідки. Відповіді лише на посилання можуть стати недійсними, якщо пов’язана сторінка зміниться. - З огляду
Жан-Франсуа Фабр

3
Дякую Жан. Я включив основні частини коду у відповідь і надав посилання для довідки, як пропонується.
Temi Lajumoke

тепер це починає виглядати добре. +1 (бо зараз ти не заслуговуєш -1)
Жан-Франсуа Фабр

1
У новій частині ApplicationUser, чи не було б краще додати EmailConfirmed = true?
egmfrs

9
@mahmoudfathy Add services.AddDefaultIdentity<ApplicationUser>().AddRoles<IdentityRole>().AddEntityFrameworkStores<DbContext>();to yourConfigureServices
Денніс де Лаат

26

Відповідь Темі майже правильна, але ви не можете викликати асинхронну функцію з не асинхронної функції, як він пропонує. Що вам потрібно зробити, це зробити асинхронні виклики в синхронній функції так:

    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 <> та примушування системи чекати дещо по-іншому синхронно.


Я не думаю, що ваша відповідь відповідає питанням.
The_Black_Smurf

Насправді я вважаю, що це одна з найкращих відповідей, АЛЕ, я б не використовував ті ПОРТНІ Завдання <bool> hasAdminRole = roleManager.RoleExistsAsync ("Адміністратор"); і замість цього використовуйте var adminRoleExist = roleManager.RoleExistsAsync ("Адміністратор"). Результат; Також мені не подобається той факт, що електронна пошта є жорстко закодованою, перемістіть другу частину до контролера реєстру, і якщо жодного адміністратора не існує, користувач автоматично додається до ролі адміністратора ...
L.Trabacchin

1
Чому б не помістити це в програму, де головним може бути Async, і ми використовуємо конфігурацію Roles як розширення IWebHost. Здається, це пропонують деякі Microsofties (розширення, а не основна асинхронізація): docs.microsoft.com/en-us/archive/msdn-magazine/2019/april/…
Пауло Невес,

8

Я використовую це (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
}

1
ApplicationRole введено в IdentityRole через те, що я налаштував первинний ключ ідентифікатора як GUID ( docs.microsoft.com/en-us/aspnet/core/security/authentication/… )
harveyt

Як ти це називаєш?
Річард Барракло

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

3

На додаток до відповіді Temi Lajumoke, варто зазначити, що після створення необхідних ролей та призначення їх певним користувачам у веб-програмі ASP.NET Core 2.1 MVC , після запуску програми, ви можете зіткнутися з помилкою методу, наприклад, реєстрацією або керуванням рахунок:

InvalidOperationException: Не вдається вирішити службу типу "Microsoft.AspNetCore.Identity.UI.Services.IEmailSender" під час спроби активувати "WebApplication.Areas.Identity.Pages.Account.Manage.IndexModel".

Подібну помилку можна швидко виправити в методі ConfigureServices, додавши метод AddDefaultUI ():

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.


2

Оновлення в 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();
   }

0

У методі Налаштування оголосіть менеджера ролей (автозавантаження)

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

НЕОБОВ’ЯЗКОВО - у налаштуваннях додатків.JSON (це залежить від вас, звідки ви хочете отримувати ролі)

{
"Roles": [
"SuperAdmin",
"Admin",
"Employee",
"Customer"
  ]
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.