2

考虑以下简化场景:

public class Person
{
    public string Name { get; set; }

    public int Age { get; set; }

    // restricted
    public string SocialSecurityNumber { get; set; }

    // restricted
    public string MothersMaidenName { get; set; }
}

因此,在应用程序中,许多用户可以查看Person数据。部分用户可以查看全部;其他用户只能查看NameAge

在客户端让 UI 仅显示授权数据很容易,但我真的不想将该数据发送到客户端。

我试图通过创建FullPerson : BasicPerson层次结构(每类层次结构表)来实现这一点。我使用了 a 的两个实现StaffRepository来获得所需的类型,但是由于 NH 代理,必要的转换在运行时失败。当然,在 RDBMS 中,People表中的任何给定行都可以表示 aFullPerson或 a BasicPerson,并且给它们两个相同的鉴别器值也不起作用。

我只考虑映射FullPerson并使用AliasToBean结果转换器过滤到BasicPerson,但我理解这是一条单向街道,而我希望在会议。

我的另一个想法是将所有受限字段包装到一个类中并将其添加为属性。我对这种方法的担忧有几个:

  1. 它损害了我的域模型,
  2. 我必须将该属性声明为一个集合(始终为 1)才能使其延迟加载,并且
  3. 我什至不确定如何防止加载该惰性集合。

这一切都感觉不对劲。是否有已知的方法来达到预期的结果?

澄清:

这在仅限 Intranet 的桌面应用程序中;会话存在于客户端上。虽然我当然可以创建一个中间服务层,但我必须放弃延迟加载和更改跟踪,我真的很想保留这些。

4

2 回答 2

2

我将不理会您的域模型,而是使用Automapper根据当前用户的安全级别(或您用来确定对特定属性的访问权限的任何标准)映射到特定的 DTO。这应该在位于 UI 和存储库之间的某种服务层中完成。

编辑:

根据您保持延迟加载和更改跟踪的要求,也许使用代理模式来包装您的域对象是一个可行的选择?您可以将原始域模型包装在对每个给定属性执行安全检查的代理中。我相信CSLA.NET使用这样的方法来实现字段级安全性,因此可能值得浏览源代码以获得一些灵感。您也许可以更进一步,使用代理实现的接口,这些接口只公开用户有权访问的属性。

于 2010-09-07T17:40:43.500 回答
2

首先,让我说,我不认为 N​​Hibernate 有责任处理安全性,以及基于相同的数据编辑。我认为您尝试将其放在数据访问层中会使它过于复杂。

我会在从客户端(不应该是存储库本身)接收此数据请求的服务或控制器中插入一个层,并将根据用户权限执行数据编辑。因此,您将对数据库执行完整查询,然后根据用户权限,服务层将在通过服务连接返回该结果集之前清除结果集的字段。它不是绝对最高性能的解决方案,但比将所有数据发送到客户端并让客户端软件“审查”它更安全、更高效。服务器架构的 DB 和服务层之间的以太网连接可以处理比服务层和客户端之间的 Internet 连接更多的带宽,在远程客户端应用程序中,您通常几乎无法控制客户端对数据的处理方式;您可能正在与您的软件或类似软件的被黑副本交谈,这不会对用户安全性进行两次翻转。

如果服务和数据库之间的网络带宽非常重要,或者如果大量信息受到限制,Linq2NH 应该足够聪明,让您可以使用选择列表指定查询结果中应该或不应该包含的内容:

if(!user.CanSeeRestrictedFields)
   var results = from p as Repository.AsQueryable<Person>()
   //rest of Linq statement
   select new Person { 
         Name = p.Name,
         Age = p.Age
      };
else
   var results = from p as Repository.AsQueryable<Person>()
   //rest of Linq statement
   select new Person { 
         Name = p.Name,
         Age = p.Age,
         SocialSecurityNumber = p.SocialSecurityNumber,
         MothersMaidenName = p.MothersMaidenName
      };

我不知道 Linq2NH 是否足够聪明,可以将条件运算符解析为 SQL;我对此表示怀疑,但很有可能,您可以根据用户是否有权查看它们,在 SSN 和 MMN 字段的初始化程序中指定条件运算符,从而允许您组合这两个查询。

于 2010-09-07T17:47:21.440 回答