我正在使用asp.net核心默认网站模板和身份验证作为单个用户帐户。如何创建角色并将其分配给用户,以便可以在控制器中使用角色来过滤访问。
Answers:
我在帐户控制器中创建了一个操作,该操作调用一个函数来创建角色并影响默认用户的管理员角色(您可能应该在生产中删除默认用户):
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);
}
}
之后,您可以创建一个控制器来管理用户的角色。
_userManager.GetUsersInRoleAsync("admin");
我的评论已删除,因为我提供了指向我在此处回答的类似问题的链接。嗯,这次我将更描述性地回答。开始。
通过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
Startup类的方法中调用该方法。确保您IServiceProvider
在Configure
类中具有参数。
在控制器中使用基于角色的授权来过滤用户访问权限:问题2
您可以轻松地做到这一点,就像这样。
[Authorize(Roles="Manager")]
public class ManageController : Controller
{
//....
}
您也可以像这样在操作方法中使用基于角色的授权。分配多个角色,如果您愿意
[Authorize(Roles="Admin, Manager")]
public IActionResult Index()
{
/*
.....
*/
}
虽然这很好用,但为了更好的实践,您可能需要阅读有关使用基于策略的角色检查的信息。你可以找到它的ASP.NET核心文档在这里,还是这篇文章我写了一篇关于它在这里
services.AddDefaultIdentity<ApplicationUser>().AddRoles<IdentityRole>().AddEntityFrameworkStores<DbContext>();
到您的照片ConfigureServices
Temi的答案几乎是正确的,但是您不能像他建议的那样从非异步函数中调用异步函数。您需要做的是在同步函数中进行异步调用,如下所示:
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 <>类,并迫使系统以同步方式稍有不同的方式等待。
我用这个(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
}
以下代码将在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();
}
除了Temi Lajumoke的回答外,值得注意的是,在创建所需的角色并将其分配给ASP.NET Core 2.1 MVC Web应用程序中的特定用户之后,启动该应用程序后,您可能会遇到方法错误,例如注册或管理帐户:
InvalidOperationException:尝试激活“ WebApplication.Areas.Identity.Pages.Account.Manage.IndexModel”时,无法解析类型为“ Microsoft.AspNetCore.Identity.UI.Services.IEmailSender”的服务。
通过添加AddDefaultUI()方法,可以在ConfigureServices方法中快速纠正类似的错误:
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。
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();
}
在配置方法中,声明您的角色管理器(启动)
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));
}
}
}
可选-在appsettings.JSON中(取决于您要从中获取角色的位置)
{
"Roles": [
"SuperAdmin",
"Admin",
"Employee",
"Customer"
]
}