这是实现强类型角色的良好数据模型吗?

时间:2009-11-08 15:33:18

标签: c# .net nhibernate data-modeling roles

是的,在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作为join-sublass映射到NHibernate中的RoleAssignment。

因此,在Person和UserRole和AdminRole之间是1:1,在UserRole和RoleAssignment之间是1:1,在RoleAssignment和RoleDefinition之间是n:1。

我的问题是:这真的是一个好模特吗?

是否有更好的方法对此进行建模而不会失去每个角色具有强类型,可查询属性的能力?考虑到我们将继续向系统添加更多角色,它的扩展程度如何?

1 个答案:

答案 0 :(得分:3)

乍一看,我认为单个用户拥有多个登录名和密码有点奇怪,每个角色一个,除非你假设用户总是属于一个角色。例如,如果我同时属于名为AccountantSalesperson的角色,例如可能发生在小型企业中,那么根据上面的定义,我会看到两个RoleDefinition s并且,因此,两个登录名和密码。

除此之外,在过去,我已经相似地绘制了这个。有一个User类,它本质上是一个用户个人资料,并具有string UserNamestring HashedPasswordTimeZoneInfo TimeZonePreferenceISet<Role> Roles等属性,以及一个LogOn(string password)方法。

我的User类的LogOn()方法执行更新FailedLogonsCount属性或TemporaryLockoutLiftedAtUtc属性等操作,具体取决于是否对传入的密码进行哈希处理一个存储,或者它返回一个实现IPrincipal的非持久化对象,这是一个standard .NET interface

从这个意义上说,我区分了用户的个人资料(User类)和他们的身份验证/授权令牌(实现IPrincipalIIdentity的非持久化类,以便他们可以参与.NET框架中使用的各种[Authorize]Thread.CurrentPrincipal方案。当User实例创建实现IPrincipal的对象时,它只是将用户角色的副本作为字符串数组传递,以便IPrincipal的{​​{1}}方法将工作

这意味着我的角色名称本质上是神奇的,众所周知的字符串,实际上是角色数据库表中的唯一键。但我不认为这有很多方法。的确,我的IsInRole()课程看起来像这样:

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 }UserRole因为类本身具有单独的行为吗?我认为它们只是通用AdminRole类的不同数据点,因此您不需要为每个类分别设置子类。

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

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