我正在尝试在ASP.NET MVC应用程序中创建权限系统。我一直在学习最新的身份框架 - 这是我的要求:
通过扩展ASP.NET身份,我可以完成所有这些吗?或者我应该从头开始构建一些定制的东西吗?
答案 0 :(得分:7)
实施您自己的身份验证系统的10,000个中有9,999次是错误的方法。任何事情都比这更容易,而正确是一件看似困难的事情。 ASP.NET Identity实际上是可定制的,因为它是专门为此目的而创建的。您可能需要做很多工作才能完全引导您的自定义需求,但使用ASP.NET标识几乎肯定会更快更安全。
<强>更新强>
UserManager
的构造函数采用IUserStore
的实现。在使用Entity Framework时,您通常只需提供它Microsoft.AspNet.Identity.EntityFramework.UserStore
,但这是您可扩展性的关键点。因此,您可以简单地继承UserStore
,然后覆盖类似GetRolesAsync
的内容,以执行您需要实现的任何自定义角色逻辑。那么你只需要提供UserManager
你的子类。
答案 1 :(得分:7)
在ASP.NET成员资格的1.0版中,IRole
接口必须具有string
主键。但是,在2014年3月发布的2.0版中,他们添加了IRole<TKey>
,允许您指定角色的主键,只要TKey
实现IEquatable<TKey>
。
也就是说,开箱即用的MVC集成点仍然取决于单个字符串ID的角色。因此,如果您要通过Authorize这样的属性进行授权,那么您可能需要编写自己的自定义授权属性。
实现分层角色的一种方法是在应用程序中而不是在模型中处理它。我假设按层次结构,您的意思是管理员拥有管理员的所有权限,管理员具有与编辑者相同的权限,依此类推。您可以通过将用户添加到多个角色来实现此目的,而不必遍历建模的角色层次结构。类似于db触发器的东西可以做到这一点,但您也可以将其建模为代码中的业务规则。然后,如果您将页面限制为编辑器,管理员&amp;经理们也可以访问它。
另一种方法是仅为多个角色授权某些操作:
[Authorize(Roles = "Administrator, Manager, Editor")]
public ActionResult Edit()
[Authorize(Roles = "Administrator, Manager")]
public ActionResult Manage()
[Authorize(Roles = "Administrator")]
public ActionResult Admin()
我不同意你想要在复合键上识别角色。如果要使用Authorize属性保护MVC操作,则角色的ID必须是常量值,如字符串文字,int或Enum值等。如果您在多个属性上键入了角色,则该数字您需要在属性上设置的属性乘以ID的每个组件中的值的数量。您将拥有Manager / SiteA,Manager / SiteB等。
相反,听起来像添加属性来追踪角色中的用户(多对多关系中的中间表)可能是一个好主意。要做到这一点,您将无法像@Chris Pratt建议的那样简单地覆盖和扩展UserManager类中的方法。但这并不意味着你必须把洗澡水扔掉。您仍然可以使用Microsoft.AspNet.Identity进行身份验证,只需编写自己的角色管理方法,将其扩充为另外一个参数:
AddToRoleAsync(TUser user, string roleName, string siteId);
public class Role : IRole<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorizes { get; set; }
}
public class UserInRole
{
public int RoleId { get; set; } // part of composite primary key
public int UserId { get; set; } // part of composite primary key
public string SiteId { get; set; } // part of composite primary key
public virtual Role Role { get; set; }
public virtual User User { get; set; }
}
public class User : IUser<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorized { get; set; }
}
鉴于上述情况,请说明您的网址如下:
/sites/site-a/admin
/sites/site-b/manage
/sites/site-c/edit
/sites/{siteId}/do
...您可以编写一个自定义授权属性来检查URL,并根据属性中的角色名称和URL中的siteId对主体进行授权。要从属性访问数据库,如果您正在使用IoC for EntityFramework,您可以使用属性注入DbContext的实例(或者包装它的任何接口)。