Как создавать роли в ядре asp.net и назначать их пользователям
Я использую шаблон сайта веб-сайта asp.net core default и аутентификацию, выбранную как отдельная учетная запись пользователя. Как создать роль и назначить ее пользователю, чтобы я мог использовать роль в контроллере для фильтрации доступа.
Ответы
Ответ 1
Я создал действие в контроллере учетных записей, которое вызывает функцию для создания ролей и влияет на роль администратора для пользователя по умолчанию (вам, вероятно, следует удалить пользователя по умолчанию в рабочей среде):
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);
}
}
После вы можете создать контроллер для управления ролями для пользователей.
Ответ 2
Мой комментарий был удален, потому что я предоставил ссылку на похожий вопрос, на который я ответил здесь. Ergo, на этот раз я отвечу более информативно. Вот оно.
Вы можете легко сделать это, создав метод 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 здесь, или эту статью, которую я написал об этом здесь
Ответ 3
Ответ Теми почти правильный, но вы не можете вызывать асинхронную функцию от неасинхронной функции, как он предлагает. Что вам нужно сделать, так это сделать асинхронные вызовы в синхронной функции:
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, "[email protected]!");
newUser.Wait();
if (newUser.Result.Succeeded)
{
Task<IdentityResult> newUserRole = userManager.AddToRoleAsync(administrator, "Administrator");
newUserRole.Wait();
}
}
}
Ключом к этому является использование класса Task <> и принуждение системы подождать немного по-другому синхронно.
Ответ 4
Я использую это (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
}
Ответ 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 = "[email protected]";
string adminPwd = "[email protected]!";
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();
}
Ответ 6
В дополнение к ответу 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.
Ответ 7
Я создал PowerUser из данных настроек приложения, но при входе в систему отображается сообщение "Недопустимая попытка входа". Ты хоть представляешь почему?