Estoy usando asp.net core plantilla de sitio web por defecto y la autenticación seleccionada como cuenta de usuario individual. Cómo puedo crear un rol y asignarlo al usuario para que pueda utilizar el rol en el controlador para filtrar el acceso.
Mi comentario fue borrado porque proporcioné un enlace a una pregunta similar que respondí aquí. Ergo, esta vez responderé de forma más descriptiva. Allá va.
Podrías hacer esto fácilmente creando un método CreateRoles
en tu clase startup
. Esto ayuda a comprobar si los roles están creados, y crea los roles si no lo están; en el arranque de la aplicación. Así.
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 entonces podrías llamar al método CreateRoles(serviceProvider).Wait();
desde el método Configure
en la clase Startup.
asegúrate de que tienes IServiceProvider
como parámetro en la clase Configure
.
Utilizar la autorización basada en roles en un controlador para filtrar el acceso de los usuarios: Pregunta 2
Puedes hacer esto fácilmente, así.
[Authorize(Roles="Manager")]
public class ManageController : Controller
{
//....
}
También puede utilizar la autorización basada en roles en el método de acción así. Asignar múltiples roles, si lo desea
[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 la política basada en la función de verificación. Puedes encontrarlo en la documentación de ASP.NET core aquí, o en este artículo que escribí sobre ello aquí
He creado una acción en el controlador de cuentas que llama a una función para crear los roles y afectar el rol de administrador a un usuario por defecto (Probablemente deberías eliminar el usuario por defecto 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 de que usted podría crear un controlador para gestionar los roles de los usuarios.
Temi's respuesta es casi correcta, pero no se puede llamar a una función asíncrona de una función no asíncrona como él está sugiriendo. Lo que tienes que hacer es hacer llamadas asíncronas en una función síncrona así:
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 de esto es el uso de la clase Task<> y forzar al sistema a esperar de una manera ligeramente diferente en una forma sincrónica.