MVC 6组权限无法获得角色

时间:2016-07-19 16:24:18

标签: c# entity-framework asp.net-core asp.net-core-mvc

我将ASP.NET Identity 2.0: Implementing Group-Based Permissions Management转换为ASP.NET Core,一切都很好,但我无法从群组中获得角色

继承人代码:

ApplicationGroup实体

public sealed class ApplicationGroup
{
    [Key]
    public string Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public ICollection<ApplicationGroupRole> ApplicationGroupRoles { get; set; }
    public ICollection<ApplicationGroupUser> ApplicationGroupUsers { get; set; }

    public ApplicationGroup()
    {
        Id = Guid.NewGuid().ToString();
        ApplicationGroupRoles = new List<ApplicationGroupRole>();
        ApplicationGroupUsers = new List<ApplicationGroupUser>();
    }

}

ApplicationGroupRole实体

public class ApplicationGroupRole
{
    public string ApplicationRoleId { get; set; }

    public string ApplicationGroupId { get; set; }
    [ForeignKey("ApplicationGroupId")]
    public ApplicationGroup ApplicationGroup { get; set; }

}

ApplicationGroupUser实体

public class ApplicationGroupUser
{
    public string ApplicationUserId { get; set; }

    public string ApplicationGroupId { get; set; }
    [ForeignKey("ApplicationGroupId")]
    public ApplicationGroup ApplicationGroup { get; set; }

}

DbContext OnModelCreating:

        modelBuilder.Entity<ApplicationGroup>()
            .HasMany(u => u.ApplicationGroupUsers);

        modelBuilder.Entity<ApplicationGroupUser>()
            .HasKey(r => new {r.ApplicationUserId, r.ApplicationGroupId});

        modelBuilder.Entity<ApplicationGroup>()
            .HasMany(g => g.ApplicationGroupRoles);

        modelBuilder.Entity<ApplicationGroupRole>()
            .HasKey(gr => new { gr.ApplicationRoleId, gr.ApplicationGroupId});

        modelBuilder.Entity<ApplicationGroupUser>().ToTable("ApplicationUserGroups");

        modelBuilder.Entity<ApplicationGroupRole>().ToTable("ApplicationRoleGroups");

        modelBuilder.Entity<ApplicationGroup>().ToTable("ApplicationGroups");

控制器:

    public ActionResult Details(string id)
    {
        if (id == null)
        {
            return new StatusCodeResult(400);
        }
        ApplicationGroup applicationgroup = _groupManager.Groups.FirstOrDefault(g => g.Id == id);
        if (applicationgroup == null)
        {
            return new NotFoundResult();
        }
        var groupRoles = _groupManager.GetGroupRoles(applicationgroup.Id);
        var RoleNames = groupRoles.Select(p => p.Name).ToArray();
        ViewBag.RolesList = RoleNames;
        ViewBag.RolesCount = RoleNames.Count();
        return View(applicationgroup);
    }

查看:

@model ApplicationGroup

@{
    ViewBag.Title = "Details";
}
<h2>Details</h2>
<div>
    <h4>ApplicationGroup</h4>
    <hr />
    <dl class="dl-horizontal">
        <dt>
            @Html.DisplayNameFor(model => model.Name)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Name)
        </dd>
        <dt>
            @Html.DisplayNameFor(model => model.Description)
        </dt>
        <dd>
            @Html.DisplayFor(model => model.Description)
        </dd>
    </dl>
</div>
<h4>List of permissions granted this group</h4>
@if (ViewBag.PermissionsCount == 0)
{
    <hr />
    <p>No users found in this role.</p>
}
<table class="table">
    @foreach (var item in ViewBag.RolesList)
    {
        <tr>
            <td>
                @item
            </td>
        </tr>
    }
</table>
<p>
    @Html.ActionLink("Edit", "Edit", new { id = Model.Id }) |
    @Html.ActionLink("Back to List", "Index")
</p>

结果是当我到达视图时,没有角色,请帮忙修复此问题,我哪里出错了? Screen Shoot

解决方案更新:

需要将控制器更改为:

public ActionResult Details(string id)
{
    if (id == null)
    {
        return new StatusCodeResult(400);
    }
    var applicationgroup = _groupManager.Groups
            .Where(g => g.Id == id)
            .Select(g => new ApplicationGroup()
            {
                ApplicationGroupRoles = g.ApplicationGroupRoles
            }).FirstOrDefault();

    if (applicationgroup == null)
    {
        return new NotFoundResult();
    }
    var groupRoles = _groupManager.GetGroupRoles(applicationgroup.Id);
    var RoleNames = groupRoles.Select(p => p.Name).ToArray();
    ViewBag.RolesList = RoleNames;
    ViewBag.RolesCount = RoleNames.Count();
    return View(applicationgroup);
}

并且需要将其他类中的某些查询更改为:

            var grp = _db.ApplicationGroups
            .Where(y => y.Id == groupId)
            .Select(g => new ApplicationGroup()
            {
                ApplicationGroupRoles = g.ApplicationGroupRoles
            })
            .FirstOrDefault();

2 个答案:

答案 0 :(得分:2)

在Identity 2中,我做了类似于您引用的组权限项目的操作。除了我将它们命名为Profiles而不是Groups。我开始在Identity Core中做同样的事情但后来意识到我可以使用一个名为 UserRoleClaim 的新身份表。使用这个新表,我完成了同样的事情,而无需修改Identity Core数据库模式。另外,我不必编写自己的EF代码。一切都可以使用UserManagerRoleManager类中的内置方法完成。

您现在可以将一个组等同于一个角色。每个角色可以有许多声明,许多用户可以属于某个角色。授权用户的关键是与用户所属角色相关的声明。您不能直接在authorize属性中使用声明(这将是混乱的)。您必须将声明与策略相关联。 策略是Identity Core的绝佳之处!他们可以将您的声明组织到配置文件中。然后,您只需要在Authorize属性中添加配置文件。这比在身份2中添加角色和/或声明列表要好得多。

使用启动类的services.AddAuthorization()方法中的ConfigureServices()方法创建配置文件。

services.AddAuthorization(options =>
{
    options.AddPolicy("Product", policy => policy.RequireClaim("Product"));
    options.AddPolicy("ProductEdit", policy => policy.RequireClaim("Product", "Edit"));
});

您可以在“授权”属性中使用这些策略。

[Authorize(Policy = "Product")]
public class ProductController : Controller
{
    [HttpGet]
    public IActionResult Index()
    {
        return View();
    }

    [HttpGet]
    [Authorize(Policy = "ProductEdit")]
    public IActionResult Edit()
    {
        return View();
    }
}

在做出任何设计决定之前,我会阅读Identity Core中的授权。该文档实际上非常好并且易​​于阅读。我建议至少阅读这些文章 Claims-Based Authorization
Policy-Based Authorization

我已经在Identity Core中描述了声明和基于策略的授权的基础知识。但请按照我上面链接的文档中的其他文章进行操作,您会看到还有更多选项供您使用。

答案 1 :(得分:1)

第1步是直接检查您的数据库,并确保您有一些ApplicationGroupRole行,其ApplicationGroupId对应于该屏幕截图中可以看到的Id guid

如果您这样做,则问题可能是您在查询中未包含ApplicationGroupRoles的问题。

要添加ApplicationGroupRoles,您可以使用Include扩展方法。确保你有这个使用声明。

using System.Data.Entity

然后像这样进行查询

ApplicationGroup applicationgroup = _groupManager.Groups
    .Include(g => g.ApplicationGroupRoles)
    .FirstOrDefault(g => g.Id == id);

请注意:如果在从数据库返回之前将结果投影到视图模型上,则不需要Include语句。 I.E.

var VM = _groupManager.Groups
    .Where(g => g.Id == id)
    .Select(g => new MyGroupViewModel()
    {
        Roles = g.ApplicationGroupRoles
    })
    .FirstOrDefault();
相关问题