.NET Core 2.1 MVC身份授权-不同部分的不同用户角色

时间:2018-06-26 14:36:24

标签: asp.net-core asp.net-core-mvc asp.net-core-2.0 asp.net-core-identity

目前,我正在一个项目管理网站上。系统中有一个SuperAdmin(角色),可以创建新项目。 SuperAdmin可以将用户分配给具有不同角色的这些项目,例如admin或观察者。用户可以为不同的项目扮演不同的角色,甚至根本没有任何角色。
例如:

  1. 用户A是项目A的管理员
  2. 用户A是项目B的观察者(只读)
  3. 用户A没有角色C(无法访问该项目)
  4. 用户B是项目B的管理员
  5. 用户B是项目C的观察员(仅读访问权限)

“身份”似乎不支持这种行为。基于声明的授权似乎支持静态声明,但不支持动态声明(访问具有ID的项目)。 我可以创建自己的UserProjectRoles类,该类将用户,项目和角色关联在一起,并在授权处理程序(基于策略的授权)中使用该类,但是我想知道这是否是正确的解决方案。您将如何解决此任务?

编辑:

我最终完成了以下操作:我创建了一个新的UserProjectClaims表,该表连接了Users和Projects,并将角色类型包含为枚举(我将角色/声明类型移到它自己的表中,这只是为了为了测试)。

public class UserProjectClaim
{
    public int ProjectId { get; set; }
    public Project Project { get; set; }

    public int UserId { get; set; }
    public AppUser User { get; set; }

    public UserProjectClaimEnum ClaimType { get; set; }
}

然后,如基于策略的授权教程中所见,我在AuthorizationHandler中使用了该表:

protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, ProjectAdminRequirement requirement)
{
    if (context.Resource is AuthorizationFilterContext authContext)
    {
        var projectId = Int32.Parse(authContext.HttpContext.Request.Query["projectId"]);
        var userid = (await _userManager.GetUserAsync(context.User)).Id;
        var claim = _dbContext.AppUsers.Include(i=>i.UserProjectClaims).Single(u=>u.Id==userid).UserProjectClaims.SingleOrDefault(p => p.ProjectId == projectId);      

        if (claim != null && claim.ClaimType == Data.Enums.UserProjectClaimEnum.ProjectAdmin)
        {
            context.Succeed(requirement);
        }
        else
        {
            context.Fail();
        }
    }           
}

它按预期工作。

1 个答案:

答案 0 :(得分:1)

在使用个人用户帐户(VS2017)创建新的Web应用程序(MVC)之后,您会发现诸如AspNetRoles,AspNetRoleClaims,AspNetUserRoles,AspNetUserClaims之类的表作为实体框架核心IdentityContext的一部分。

AccountController注入了一个UserManager,但是没有维护Roles&Claims的方法。没有提供开箱即用的视图(页面),控制器和模型来管理关系。

好消息是UserManager具有各种功能,可以向用户添加声明和角色。 AddClaimAsync,AddToRoleAsync,GetClaimsAsync,GetRolesAsync,GetUsersForClaimAsync,GetUsersInRoleAsync,RemoveClaimAsync,RemoveFromRoleAsync以及将声明/角色作为IEnumerable处理的版本。

短期解决方案:向AccountController或ManageController添加方法,甚至创建RolesController来支持管理这些关系的页面,都不是一件容易的事。

长期解决方案:了解如何在创建新的MVC Identity项目时添加模板以生成这些项目。然后通过在GitHub上公开它来炫耀一下:)或写一篇关于您在所处情况下向其他人学到的东西的文章。

后记:通过创建一个放置在请求处理路径中的中间件,您可以为当前用户加载其余请求可以引用的角色/声明。从Projects到Roles的联接表(可能具有读取角色和写入角色),您可以将所需的角色与用户拥有的角色/声明进行比较。

技术:Here是自定义策略和授权的绝佳解释。对于您的情况,该策略将测试用户是否具有与您的项目匹配的角色/声明。您在上面的角色实际上是Project-Read,Project-Write。如果没有,则无法访问。