tutorial net mvc multiple example authorizeattribute asp c# asp.net asp.net-mvc asp.net-core asp.net-identity-3

net - c# authorizeattribute multiple roles



Cómo crear roles en asp.net core y asignarlos a usuarios (6)

Además de la respuesta de Temi Lajumoke, vale la pena señalar que después de crear los roles requeridos y asignarlos a usuarios específicos en la aplicación web ASP.NET Core 2.1 MVC , después de iniciar la aplicación, puede encontrar un error de método, como registrar o administrar un cuenta:

InvalidOperationException: no se puede resolver el servicio para el tipo ''Microsoft.AspNetCore.Identity.UI.Services.IEmailSender'' al intentar activar ''WebApplication.Areas.Identity.Pages.Account.Manage.IndexModel''.

Un error similar se puede corregir rápidamente en el método ConfigureServices agregando el método AddDefaultUI ():

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

Comprobar

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

y tema relacionado en github:

https://github.com/aspnet/Docs/issues/6784 para más información.

Y para asignar un rol a un usuario específico se podría usar la clase IdentityUser en lugar de ApplicationUser.

Estoy usando la plantilla predeterminada del sitio web asp.net core y la autenticación seleccionada como cuenta de usuario individual. ¿Cómo puedo crear un rol y asignarlo al usuario para que pueda usar el rol en el controlador para filtrar el acceso?


Creé una acción en el controlador de cuenta que llama a una función para crear los roles y afecta el rol de administrador a un usuario predeterminado (Probablemente debería eliminar el usuario predeterminado en producción):

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 = "[email protected]"; 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); } }

Después, podría crear un controlador para administrar roles para los usuarios.


El siguiente código funcionará 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 = "[email protected]"; 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(); }


La respuesta de Temi es casi correcta, pero no se puede llamar a una función asincrónica desde una función no asincrónica como sugiere. Lo que debe hacer es realizar llamadas asincrónicas en una función síncrona como esta:

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 = "[email protected]"; //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 clave para esto es el uso de la clase Tarea <> y obligar al sistema a esperar de una manera ligeramente diferente de forma síncrona.


Mi comentario fue eliminado porque proporcioné un enlace a una pregunta similar que respondí here . Ergo, lo responderé más descriptivamente esta vez. Aquí va.

Puede hacerlo fácilmente creando un método CreateRoles en su clase de startup . Esto ayuda a verificar si los roles se crean y crea los roles si no lo son; en el inicio de la aplicación. Al igual que.

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

y luego puede llamar a CreateRoles(serviceProvider).Wait(); método del método Configure en la clase Startup. asegúrese de tener IServiceProvider como parámetro en la clase Configure .

Uso de la autorización basada en roles en un controlador para filtrar el acceso del usuario: Pregunta 2

Puedes hacer esto fácilmente, así.

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

También puede usar la autorización basada en roles en el método de acción de esta manera. Asigna múltiples roles, si quieres

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

Si bien esto funciona bien, para una práctica mucho mejor, es posible que desee leer sobre el uso de comprobaciones de roles basadas en políticas. Puede encontrarlo en la documentación básica de ASP.NET here , o en este artículo que escribí al respecto here


Yo uso esto (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 = "[email protected]", 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 }