【问题标题】:Is this a good data model to implement strongly-typed roles?这是实现强类型角色的良好数据模型吗?
【发布时间】:2010-12-14 09:21:26
【问题描述】:

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

所以,这是 Person 与 UserRole 和 AdminRole 之间的 1:1,UserRole 和 RoleAssignment 之间的 1:1,以及 RoleAssignment 和 RoleDefinition 之间的 n:1。

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

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

【问题讨论】:

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


    【解决方案1】:

    乍一看,我认为单个用户拥有多个登录名和密码(每个角色一个)有点奇怪,除非您假设一个用户始终属于一个角色。例如,如果我同时属于名为 AccountantSalesperson 的角色,例如可能发生在小型企业中,那么根据上面的定义,我将拥有两个 RoleDefinitions,因此,两个登录名和密码。

    除此之外,在过去,我也有类似的映射。有一个User 类,它本质上是一个用户配置文件,具有string UserNamestring HashedPasswordTimeZoneInfo TimeZonePreferenceISet&lt;Role&gt; Roles 等属性,以及一个LogOn(string password) 方法。

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

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

    这意味着我的角色名称本质上是神奇的、众所周知的字符串,实际上是角色数据库表中的唯一键。但我不认为有太多的方法可以解决这个问题。事实上,我的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 提供的基于角色的安全模型的简单性。

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

    【讨论】:

    • 感谢 Nicholas 的详细回答。从我最初的问题描述中并不清楚,但这个想法是让角色有可能具有可查询的属性。我的特定场景中更具体的示例是具有登录名和密码的“用户”角色,以及具有分配的类列表的“学生”角色。一个人可能是用户和/或学生,我可以使用他们的属性查询任一角色。我将添加约束,以便一个角色只能分配给一个用户一次,因此一个人永远不会有两个登录名和密码。
    猜你喜欢
    • 1970-01-01
    • 2012-03-30
    • 2022-10-21
    • 1970-01-01
    • 2013-06-02
    • 2017-01-09
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多