106 votes

Comment créer des rôles dans ASP.NET Core et les attribuer aux utilisateurs ?

J'utilise le modèle de site Web par défaut d'ASP.NET Core et l'authentification est sélectionnée comme "Comptes d'utilisateurs individuels". Comment puis-je créer des rôles et les attribuer aux utilisateurs afin de pouvoir utiliser les rôles dans un contrôleur pour filtrer l'accès ?

0 votes

Savez-vous comment identifier les rôles des utilisateurs lors de la connexion ?

126voto

Temi Lajumoke Points 1130

Mon commentaire a été supprimé parce que j'ai fourni un lien vers une question similaire à laquelle j'ai répondu. aquí . Par conséquent, je vais répondre de manière plus descriptive cette fois-ci. C'est parti.

Vous pouvez le faire facilement en créant un CreateRoles dans votre startup classe. Cela permet de vérifier si les rôles sont créés, et de les créer s'ils ne le sont pas, au démarrage de l'application. Ainsi.

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

            }
       }
    }

et ensuite vous pourriez appeler le CreateRoles(serviceProvider).Wait(); de la méthode Configure dans la classe Startup. Assurez-vous que vous avez IServiceProvider en tant que paramètre dans le Configure classe.

Utilisation de l'autorisation basée sur les rôles dans un contrôleur pour filtrer l'accès des utilisateurs : Question 2

Vous pouvez le faire facilement, comme ceci.

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

Vous pouvez également utiliser l'autorisation basée sur les rôles dans la méthode d'action comme suit. Attribuez plusieurs rôles, si vous le souhaitez

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

Bien que cela fonctionne bien, pour une meilleure pratique, vous pouvez lire l'article sur l'utilisation des contrôles de rôle basés sur des politiques. Vous pouvez le trouver sur la documentation ASP.NET core aquí ou cet article que j'ai écrit à ce sujet aquí

2 votes

Bien que ce lien puisse répondre à la question, il est préférable d'inclure les parties essentielles de la réponse ici et de fournir le lien pour référence. Les réponses ne comportant qu'un lien peuvent devenir invalides si la page liée change. - De la revue

3 votes

Merci Jean. J'ai inclus les parties essentielles du code dans la réponse et j'ai fourni des liens pour référence, comme suggéré.

0 votes

Maintenant ça commence à avoir l'air bien. +1 (parce que vous ne méritez pas un -1 maintenant)

73voto

Stephane Duteriez Points 526

J'ai créé une action dans le Accounts qui appelle une fonction pour créer les rôles et assigner le Admin à l'utilisateur par défaut. (Vous devriez probablement supprimer l'utilisateur par défaut en 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);
        }
  }

Après vous pourriez créer un contrôleur pour gérer les rôles pour les utilisateurs.

0 votes

Comment puis-je obtenir la liste de tous les utilisateurs ayant des rôles, je veux révoquer les rôles et modifier les rôles associés, comment puis-je le faire ?

1 votes

@BipnPaul Pour cela vous pouvez utiliser le usermanager : _userManager.GetUsersInRoleAsync("admin");

0 votes

C'est génial mais comment attribuer ces rôles aux utilisateurs lors de l'enregistrement et identifier le rôle des utilisateurs lors de la connexion ? s'il vous plaît, aidez-moi, je suis bloqué sur ce point ?

32voto

Paul Mason Points 181

La réponse de Temi est presque correcte, mais vous ne pouvez pas appeler une fonction asynchrone depuis une fonction non asynchrone comme il le suggère. Ce que vous devez faire est de faire des appels asynchrones dans une fonction synchrone comme ceci :

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

    }

La clé est l'utilisation de la classe Task<> et le fait de forcer le système à attendre d'une manière légèrement différente, de façon synchrone.

0 votes

Je ne pense pas que votre réponse soit pertinente par rapport à la question.

0 votes

En fait, je pense que c'est l'une des meilleures réponses, MAIS, je n'utiliserais pas ces Tâche<bool> hasAdminRole = roleManager.RoleExistsAsync("Administrator") ; et j'utiliserais plutôt var adminRoleExist = roleManager.RoleExistsAsync("Administrator").Result ; Aussi, je n'aime pas le fait que l'email soit codé en dur, déplacez la deuxième partie vers le contrôleur register, et si aucun admin n'existe, l'utilisateur sera automatiquement ajouté au rôle d'administrateur...

2 votes

Pourquoi ne pas mettre cela dans le Programme où le Main peut être Async et nous utilisons la configuration des Rôles comme une extension IWebHost. Cela semble être suggéré par certains Microsoft (les extensions, pas l'asynchrone principal) : docs.microsoft.com/fr/archive/msdn-magazine/2019/avril/

8voto

harveyt Points 150

J'utilise ceci (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 votes

ApplicationRole au lieu d'IdentityRole parce que j'ai configuré la clé primaire d'Identity comme GUID ( docs.microsoft.com/fr/aspnet/core/security/authentication/ )

1 votes

Comment l'appelez-vous ?

6voto

Mohammed Osman Points 548

Le code suivant fonctionnera pour 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();
    }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X