我将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();
答案 0 :(得分:2)
在Identity 2中,我做了类似于您引用的组权限项目的操作。除了我将它们命名为Profiles而不是Groups。我开始在Identity Core中做同样的事情但后来意识到我可以使用一个名为 UserRoleClaim 的新身份表。使用这个新表,我完成了同样的事情,而无需修改Identity Core数据库模式。另外,我不必编写自己的EF代码。一切都可以使用UserManager
和RoleManager
类中的内置方法完成。
您现在可以将一个组等同于一个角色。每个角色可以有许多声明,许多用户可以属于某个角色。授权用户的关键是与用户所属角色相关的声明。您不能直接在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();