2009-11-08 95 views
0

是的,在herehere之前询问过。我很好奇,我正在考虑的方法在架构上是否合理。这是一个很好的数据模型来实现强类型角色吗?

让我试图描述想什么,我能够与我的对象模型做开始:

class Person { 
    ISet<Roles> Roles { get; set; } 
} 

class RoleDefinition { 
    string Name { get; set; } 
} 

class RoleAssignment { 
    RoleDefinition Definition { get; set; } 
    Person Person { get; set; } 
} 

class UserRole : RoleAssignment { 
    public virtual string Login { get; set; } 
    public virtual string Password { get; set; } 
} 

随着意图是能够与以下方式角色的工作:

// Find all "users" with a matching login 
from user in userRolesRepository.FindAll(u => u.Login.StartsWith("abc")) 
select user.Person; 

要做到这一点,我正在考虑以下数据模型

Person table (Id, Name) 
RoleDefinition table (Id, Name) 
RoleAssignment table (Id, DefId, PersonId) 
UserRole table (RoleAssignmentId, Login, Password) 
AdminRole table (RoleAssignmentId, ...) 

我会地图UserRole和AdminRole作为NHibernate中RoleAssignment的联合子类。

所以,Person和UserRole和AdminRole之间是1:1,UserRole和RoleAssignment之间是1:1,RoleAssignment和RoleDefinition之间是1:1。

我的问题是:这真的是一个很好的模型?

有没有更好的方法来建模,而不会失去每个角色具有强类型,可查询属性的能力?考虑到随着我们的发展,我将在系统中增加更多的角色,这将如何扩展?

回答

3

乍一看,我认为单个用户有多个登录名和密码,每个角色一个,除非您认为用户总是属于一个角色,这有点奇怪。例如,如果我都属于名为AccountantSalesperson的角色(例如可能发生在小型企业中),那么按照上面的定义似乎会有两个RoleDefinition s,因此两个登录名和密码。

除此之外,在过去,我已经类似地映射了这一点。有一个User类,它实质上是一个用户配置文件,具有诸如string UserName,string HashedPassword,TimeZoneInfo TimeZonePreference,ISet<Role> Roles等的属性以及LogOn(string password)方法。

User类的登录()方法做的东西等,这取决于是否在密码哈希传递更新FailedLogonsCount财产或TemporaryLockoutLiftedAtUtc财产等成功对一个存储,或者它返回一个非持久化的对象实施IPrincipal,这是一个standard .NET interface

在这个意义上,我的用户的配置文件(该User类)和他们的认证/授权令牌(实现IPrincipalIIdentity,使他们能够参与到整个使用的各种[Authorize]Thread.CurrentPrincipal方案非持续类区分.NET框架)。当User实例创建实现IPrincipal的对象时,它只是将用户角色的副本作为字符串数组传递,以便IPrincipalIsInRole()方法可以工作。

这意味着我的角色名称本质上是神奇的,众所周知的字符串,实际上是Roles数据库表中的唯一键。但我认为没有太多办法可以解决这个问题。事实上,我Role类看起来是这样的:

class Role { 
int? Identity { get; } // database identifier that I never really look at 
string RoleEnum { get; } // the "enumeration" that is 
         // the well-known string, used in IsInRole() 
string RoleName { get; } // a human-friendly, perhaps 
         // localizable name of the role 
}

我没有为每个角色类型不同的子类。做UserRoleAdminRole作为类真的有单独的行为内在?我会提交他们只是泛型Role类的不同数据点,所以您不需要为它们分别使用不同的子类。

当你添加一个角色到你的系统时,你要么重新编译整个shebang并更新该角色的检查(这是我所做的,我不希望频繁地添加一个角色),或者,如果您确实想要获得幻想,Role类可能会有一组Permission对象或其中的一些对象,并且您的代码可能会询问角色是否为role.AllowsUserToDoThis(),并且在一个位置拥有所有权限检查。因此,配置角色的权限集将允许您在系统运行时编辑细粒度的访问控制,但是您将失去.NET提供的基于角色的安全模型的简单性。

正如你所猜测的那样,有一百万种方法可以做到,但希望这是一些有用的反馈。祝你好运!

+0

谢谢尼古拉斯的详细解答。从我的原始问题描述中不清楚,但是想法是让角色具有可查询属性。从我的具体情况来看,更具体的例子是具有登录名和密码的“用户”角色,以及具有分配类别列表的“学生”角色。一个人可能是一个用户和/或一个学生,我可以用他们的属性查询任一角色。我将添加约束条件,以便角色只能分配给用户一次,因此一个人永远不会得到两个登录名和密码。 – Ragesh 2009-11-09 04:45:14

相关问题