使用 ASP.NET Core Identity 3 的用户角色权限

Posted

技术标签:

【中文标题】使用 ASP.NET Core Identity 3 的用户角色权限【英文标题】:Users Roles Permissions using ASP.NET Core Identity 3 【发布时间】:2017-06-25 07:46:19 【问题描述】:

我被困在我想在 asp.net mvc 核心应用程序中提供的解决方案上。我想利用新的基于声明的方法为 Web 应用程序中的标准用户、角色、权限提供解决方案。

我在这里一直遵循 Ben Foster 的逻辑 (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:创建用户、角色和声明(并关联它们)后,我需要在 Startup.cs 类的配置服务方法中注册“策略”。这使我可以将声明映射到一个或多个政策。

 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>();
    

查看:在我的用例中,我想限制没有“可以添加角色”声明与分配给他们的角色相关联的任何用户使用“添加角色”按钮。其余的视图代码不相关。我遇到的问题是,我将声明名称作为第二个参数传递给 AuthorizationService.AuthorizeAsync,而不是与声明关联的“策略”名称。我已经在下面更正了它。

@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>
        
....

最终结果:我有一个用户“admin@company.com”,该用户分配给一个角色“Admin”,该角色声称“可以添加角色”。一个角色可以有任意数量的声明。我创建了一个具有相同声明“可以添加角色”的策略,我通过可注入的 IAuthorizationService AuthorizationService 在视图中检查了该声明。如果用户没有将此声明分配给他们的角色,则返回 true 或 false 的策略检查将不会显示添加角色的按钮。借助新的 .net 核心 DI 中间件,可以通过 DI 将相同的策略检查逻辑添加到控制器或任何其他资源中。通过整个练习,我了解了 Identity 3 的强大功能,它可以利用诸如业务逻辑检查之类的东西。非常甜蜜的东西,虽然那里的作家确实需要更多的例子来帮助我们更快地了解肉。无论如何,希望这有助于未来寻找类似解决方案的开发人员。

【问题讨论】:

由于您正在使用角色,您可能会发现这篇文章有助于支持使用特权对象而不是角色检查:ardalis.com/favor-privileges-over-role-checks 【参考方案1】:

我发现了问题,我在视图中引用了声明“名称”与策略名称...

我将在上面添加注释以说明错误并说明我在做什么。非常强大的东西,感谢 Ben 和 ASP.Net 提供了超过 4.5 的改进授权解决方案。

【讨论】:

不要在更新的问题中发布答案和解决方案。把它们放在答案里!!!

以上是关于使用 ASP.NET Core Identity 3 的用户角色权限的主要内容,如果未能解决你的问题,请参考以下文章

“Identity.External”的 ASP.NET Core 标识异常

ASP.Net Core 如何在 EF Core 和 Identity 中获取用户角色

第16章 使用ASP.NET Core Identity

使用 ASP.NET Core Identity 验证控制器的使用

使用 ASP.NET Core Identity 3 的用户角色权限

ASP.NET Core Identity 3 Cookie 超时