是的,在here和here之前已经提出过此问题。我很好奇我所考虑的方法在结构上是否合理。
让我先介绍一下我想用对象模型做些什么:
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。
我的问题是:这真的是一个好模特吗?
是否有更好的方法对此进行建模而不会失去每个角色具有强类型,可查询属性的能力?考虑到我们将继续向系统添加更多角色,它的扩展程度如何?
答案 0 :(得分:3)
乍一看,我认为单个用户拥有多个登录名和密码有点奇怪,每个角色一个,除非你假设用户总是属于一个角色。例如,如果我同时属于名为Accountant
和Salesperson
的角色,例如可能发生在小型企业中,那么根据上面的定义,我会看到两个RoleDefinition
s并且,因此,两个登录名和密码。
除此之外,在过去,我已经相似地绘制了这个。有一个User
类,它本质上是一个用户个人资料,并具有string UserName
,string HashedPassword
,TimeZoneInfo TimeZonePreference
,ISet<Role> Roles
等属性,以及一个LogOn(string password)
方法。
我的User
类的LogOn()方法执行更新FailedLogonsCount
属性或TemporaryLockoutLiftedAtUtc
属性等操作,具体取决于是否对传入的密码进行哈希处理一个存储,或者它返回一个实现IPrincipal
的非持久化对象,这是一个standard .NET interface。
从这个意义上说,我区分了用户的个人资料(User
类)和他们的身份验证/授权令牌(实现IPrincipal
和IIdentity
的非持久化类,以便他们可以参与.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提供的基于角色的安全模型的简单性。
正如您可能已经猜到的那样,有一百万种方法可以做到这一点,但希望这是一些有用的反馈。祝你好运!