我坚持使用我想在asp.net mvc核心应用程序中提供的解决方案。我想在Web应用程序中提供标准用户,角色,权限的解决方案,利用新的基于声明的方法。
我一直在跟随本福斯特的逻辑(http://benfoster.io/blog/asp-net-identity-role-claims)。在下面的代码中(演示质量),我将阐述我的方法,我将发表评论以帮助展示我快速而肮脏的测试解决方案。
我遇到的挑战是,它不起作用。
//注意:我发现了这个错误,并会在未来用户寻找类似解决方案的地方发表评论。
种子类:这是一个快速而肮脏的解决方案,可以使用两个新用户,两个角色和一个角色的一些声明为数据库播种。我这是一个测试应用程序,用于学习管理我的应用程序授权的声明方法。我的完整解决方案将为每个租户提供一种方式,通过UI创建自己的角色,将1个或多个声明与角色相关联,然后为用户分配角色。我想为租户提供一种管理自己用户以及他们能做什么或不做什么的方法。这是基于声明的方法的简单实现,因为权利要求比与政策的1:1关系具有更多的权力。
public class DbInitializer
{
private ApplicationDbContext _context;
private RoleManager<ApplicationRole> _roleManager;
private UserManager<ApplicationUser> _userManager;
public DbInitializer(ApplicationDbContext context,RoleManager<ApplicationRole> roleManager, UserManager<ApplicationUser> userManager)
{
_roleManager = roleManager;
_userManager = userManager;
_context = context;
}
public async Task Initialize()
{
//RoleManager<IdentityRole> roleManager = new RoleManager<IdentityRole>();
//UserManager<ApplicationUser> userManager = new UserManager<ApplicationUser>();
_context.Database.EnsureCreated();
// Look for any students.
if (!_context.Users.Any())
{
//create user and admin role
ApplicationUser adminUser = new ApplicationUser();
adminUser.Email = "admin@company.com";
adminUser.UserName = "Admin";
var result = await _userManager.CreateAsync(adminUser, "Password-1");
var newAdminUser = await _userManager.FindByEmailAsync(adminUser.Email);
ApplicationRole adminRole = new ApplicationRole();
adminRole.Name = "Admin";
adminRole.Description = "This is the admin role.";
await _roleManager.CreateAsync(adminRole);
await _roleManager.AddClaimAsync(adminRole, new Claim("Can add roles", "add.role"));
await _roleManager.AddClaimAsync(adminRole, new Claim("Can delete roles", "delete.role"));
await _roleManager.AddClaimAsync(adminRole, new Claim("Can edit roles", "edit.role"));
await _userManager.AddToRoleAsync(newAdminUser, adminRole.Name);
//create user and basic role
ApplicationUser basicUser = new ApplicationUser();
basicUser.Email = "basic@company.com";
basicUser.UserName = "Basic";
var resultBasic = await _userManager.CreateAsync(basicUser, "Password-1");
var newBasicUser = await _userManager.FindByEmailAsync(basicUser.Email);
ApplicationRole basicRole = new ApplicationRole();
basicRole.Name = "Basic";
basicRole.Description = "This is the basic role.";
await _roleManager.CreateAsync(basicRole);
//await _roleManager.AddClaimAsync(basicRole, new Claim("Can add roles", "add.role"));
//await _roleManager.AddClaimAsync(basicRole, new Claim("Can delete roles", "delete.role"));
//await _roleManager.AddClaimAsync(basicRole, new Claim("Can edit roles", "edit.role"));
await _userManager.AddToRoleAsync(newBasicUser, basicRole.Name);
await _context.SaveChangesAsync();
}
}
}
}
Startup.CS:在创建我的用户,角色和声明(以及关联它们)之后,我需要注册“政策”&#39;在Startup.cs类的Confirgure Services方法中。这允许我将声明映射到一个或多个策略。
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
services.AddAuthorization(options =>
{
options.AddPolicy("Add Role",
policy => policy.RequireClaim("Can add roles", "add.role"));
options.AddPolicy("Edit Role",
policy => policy.RequireClaim("Can edit roles", "edit.role"));
options.AddPolicy("Delete Role",
policy => policy.RequireClaim("Can delete roles", "delete.role"));
});
services.AddMvc();
services.AddTransient<DbInitializer>();
// Add application services.
services.AddTransient<IEmailSender, AuthMessageSender>();
services.AddTransient<ISmsSender, AuthMessageSender>();
}
观点:在我的用例中,我想限制“添加角色”#39;来自任何没有&#34;可以添加角色的用户的按钮&#34;与其分配的角色相关的声明。视图代码的其余部分不相关。我遇到的问题是我将声明名称传递给AuthorizationService.AuthorizeAsync作为第二个参数vs&#39; Policy&#39;具有与之关联的声明的名称。我已经在下面纠正过了。
@model IEnumerable<ApplicationRoleListViewModel>
@using HailMarry.Models
@using Microsoft.AspNetCore.Authorization
@inject IAuthorizationService AuthorizationService
<br />
<div class="top-buffer"></div>
<div class="panel panel-primary">
<div class="panel-heading panel-head">Application Roles</div>
<div class="panel-body">
<div class="btn-group">
//Mistake
//@if (await AuthorizationService.AuthorizeAsync(User, "Can add roles"))
//Fix
@if (await AuthorizationService.AuthorizeAsync(User, "Add Role"))
{
<a id="createRoleButton" asp-action="AddRole" asp-controller="ApplicationRole" class="btn btn-primary">
<i class="glyphicon glyphicon-plus"></i> Add Role
</a>
}
....
最终结果:我有一个用户&#34; admin@company.com"分配给角色&#34;管理员&#34;它有一个声明&#34;可以添加角色&#34;。角色可以有任意数量的声明。我创建了一个具有相同声明的策略&#34;可以添加角色&#34;我通过注入IAuthorizationService AuthorizationService检查了View。如果用户未将此声明分配给其角色,则返回true或false的策略检查将不会显示添加角色的按钮。由于新的.net核心DI中间件,可以通过DI将相同的策略检查逻辑添加到控制器或任何其他资源。通过这整个练习,我学会了Identity 3的强大功能,它可以利用业务逻辑检查等功能。非常甜蜜的东西,虽然那里的作家真的需要更多的例子来帮助我们更快地获得肉。无论如何,希望这有助于未来的开发人员寻找类似的解决方案。
答案 0 :(得分:3)
我发现了这个问题,我在视图中引用了“名称”与政策名称的声明......
我将在上面添加注释来说明错误并显示我正在做的事情。非常强大的功能,感谢Ben和ASP.Net提供了超过4.5的改进授权解决方案。